Make updates menu searchable, make qi plugin a little more friendly.
This commit is contained in:
parent
226c1cf6b4
commit
cae062b142
17 changed files with 611 additions and 342 deletions
|
@ -1165,7 +1165,6 @@ IF(FTE_PLUG_QI)
|
|||
ADD_LIBRARY(plug_qi MODULE
|
||||
plugins/plugin.c
|
||||
plugins/qi/qi.c
|
||||
plugins/emailnot/md5.c
|
||||
plugins/jabber/xml.c
|
||||
)
|
||||
SET_TARGET_PROPERTIES(plug_qi PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}")
|
||||
|
|
|
@ -267,6 +267,8 @@ static void PM_FreePackage(package_t *p)
|
|||
int i;
|
||||
#endif
|
||||
|
||||
COM_AssertMainThread("PM_FreePackage");
|
||||
|
||||
if (p->link)
|
||||
{
|
||||
if (p->alternative)
|
||||
|
@ -963,6 +965,7 @@ static qboolean PM_CheckFile(const char *filename, enum fs_relative base)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void PM_Plugin_Source_CacheFinished(void *ctx, vfsfile_t *f);
|
||||
static void PM_AddSubListModule(void *module, plugupdatesourcefuncs_t *funcs, const char *url, const char *prefix, unsigned int flags)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -1015,6 +1018,9 @@ static void PM_AddSubListModule(void *module, plugupdatesourcefuncs_t *funcs, co
|
|||
|
||||
downloadablessequence++;
|
||||
}
|
||||
|
||||
if (pm_source[i].funcs && (pm_source[i].status == SRCSTAT_UNTRIED) && (pm_source[i].flags&SRCFL_ENABLED)) //cache only!
|
||||
pm_source[i].funcs->Update(pm_source[i].url, VFS_OpenPipeCallback(PM_Plugin_Source_CacheFinished, &pm_source[i]), true);
|
||||
}
|
||||
static void PM_AddSubList(const char *url, const char *prefix, unsigned int flags)
|
||||
{
|
||||
|
@ -1709,7 +1715,7 @@ void PM_EnumerateMaps(const char *partial, struct xcommandargcompletioncb_s *ctx
|
|||
{
|
||||
Q_snprintfz(mname, sizeof(mname), "%s:%s", p->name, d->name);
|
||||
if (!Q_strncasecmp(mname, partial, partiallen))
|
||||
ctx->cb(mname, NULL, NULL, ctx);
|
||||
ctx->cb(mname, p->description, NULL, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2093,26 +2099,31 @@ void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const cha
|
|||
pri = maxpri;
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
{
|
||||
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||
pri = p->priority;
|
||||
}
|
||||
minpri = pri+1;
|
||||
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
{
|
||||
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||
{
|
||||
char *qhash = (p->qhash&&*p->qhash)?p->qhash:NULL;
|
||||
unsigned int fsfl = SPF_COPYPROTECTED;
|
||||
if (!qhash || !(p->flags & DPF_SIGNATUREACCEPTED))
|
||||
fsfl |= SPF_UNTRUSTED; //never trust it if we can't provide it
|
||||
|
||||
for (d = p->deps; d; d = d->next)
|
||||
{
|
||||
if (d->dtype == DEP_FILE)
|
||||
{
|
||||
Q_snprintfz(temp, sizeof(temp), "%s/%s", p->gamedir, d->name);
|
||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
|
||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, qhash, p->packprefix, fsfl);
|
||||
}
|
||||
else if (d->dtype == DEP_CACHEFILE)
|
||||
{
|
||||
Q_snprintfz(temp, sizeof(temp), "downloads/%s", d->name);
|
||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
|
||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, qhash, p->packprefix, fsfl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2291,6 +2302,8 @@ static void PM_UnmarkPackage(package_t *package, unsigned int markflag)
|
|||
package_t *o;
|
||||
struct packagedep_s *dep;
|
||||
|
||||
COM_AssertMainThread("PM_UnmarkPackage");
|
||||
|
||||
if (pkg_updating)
|
||||
return;
|
||||
|
||||
|
@ -2686,6 +2699,7 @@ static void PM_ListDownloaded(struct dl_download *dl)
|
|||
|
||||
if (f)
|
||||
{
|
||||
if (dl->replycode != 100)
|
||||
pm_source[listidx].status = SRCSTAT_OBTAINED;
|
||||
downloadablessequence++;
|
||||
if (pm_source[listidx].flags & SRCFL_UNSAFE)
|
||||
|
@ -2772,7 +2786,7 @@ static void PM_ListDownloaded(struct dl_download *dl)
|
|||
}
|
||||
}
|
||||
static void PM_Plugin_Source_Finished(void *ctx, vfsfile_t *f)
|
||||
{
|
||||
{ //plugin closed its write end.
|
||||
struct pm_source_s *src = ctx;
|
||||
size_t idx = src-pm_source;
|
||||
if (idx < pm_numsources && ctx == &pm_source[idx])
|
||||
|
@ -2785,6 +2799,7 @@ static void PM_Plugin_Source_Finished(void *ctx, vfsfile_t *f)
|
|||
dl.status = DL_FINISHED;
|
||||
dl.user_num = src-pm_source;
|
||||
dl.url = src->url;
|
||||
dl.replycode = 200; //okay
|
||||
src->curdl = &dl;
|
||||
PM_ListDownloaded(&dl);
|
||||
}
|
||||
|
@ -2795,6 +2810,31 @@ static void PM_Plugin_Source_Finished(void *ctx, vfsfile_t *f)
|
|||
}
|
||||
VFS_CLOSE(f);
|
||||
}
|
||||
static void PM_Plugin_Source_CacheFinished(void *ctx, vfsfile_t *f)
|
||||
{ //plugin closed its write end.
|
||||
struct pm_source_s *src = ctx;
|
||||
size_t idx = src-pm_source;
|
||||
if (idx < pm_numsources && ctx == &pm_source[idx])
|
||||
{
|
||||
COM_AssertMainThread("PM_Plugin_Source_CacheFinished");
|
||||
if (!src->curdl)
|
||||
{
|
||||
struct dl_download dl;
|
||||
dl.file = f;
|
||||
dl.status = DL_FINISHED;
|
||||
dl.user_num = src-pm_source;
|
||||
dl.url = src->url;
|
||||
dl.replycode = 100;
|
||||
src->curdl = &dl;
|
||||
PM_ListDownloaded(&dl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf("PM_Plugin_Source_CacheFinished: stale\n");
|
||||
}
|
||||
VFS_CLOSE(f);
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_CLIENT) && defined(WEBCLIENT)
|
||||
static void PM_UpdatePackageList(qboolean autoupdate, int retry);
|
||||
|
@ -2871,7 +2911,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
|
|||
|
||||
if (pm_source[i].funcs)
|
||||
{
|
||||
pm_source[i].funcs->Update(pm_source[i].url, VFS_OpenPipeCallback(PM_Plugin_Source_Finished, &pm_source[i]));
|
||||
pm_source[i].funcs->Update(pm_source[i].url, VFS_OpenPipeCallback(PM_Plugin_Source_Finished, &pm_source[i]), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2925,7 +2965,7 @@ qboolean PM_RegisterUpdateSource(void *module, plugupdatesourcefuncs_t *funcs)
|
|||
}
|
||||
}
|
||||
else
|
||||
PM_AddSubListModule(module, funcs, va("plug:%s", funcs->description), NULL, SRCFL_PLUGIN);
|
||||
PM_AddSubListModule(module, funcs, va("plug:%s", funcs->description), NULL, SRCFL_PLUGIN|SRCFL_ENABLED); //plugin sources default to enabled as you can always just disable the plugin that provides it.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2973,13 +3013,243 @@ static void COM_QuotedKeyVal(const char *key, const char *val, char *buf, size_t
|
|||
|
||||
Q_strncatz(buf, "\"\n", bufsize);
|
||||
}
|
||||
static void PM_WriteInstalledPackage_v3(package_t *p, char *buf, size_t bufsize)
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
|
||||
buf[0] = '{';
|
||||
buf[1] = '\n';
|
||||
buf[2] = 0;
|
||||
COM_QuotedKeyVal("package", p->name, buf, bufsize);
|
||||
COM_QuotedKeyVal("category", p->category, buf, bufsize);
|
||||
if (p->flags & DPF_ENABLED)
|
||||
COM_QuotedKeyVal("enabled", "1", buf, bufsize);
|
||||
if (p->flags & DPF_GUESSED)
|
||||
COM_QuotedKeyVal("guessed", "1", buf, bufsize);
|
||||
if (*p->title && strcmp(p->title, p->name))
|
||||
COM_QuotedKeyVal("title", p->title, buf, bufsize);
|
||||
if (*p->version)
|
||||
COM_QuotedKeyVal("ver", p->version, buf, bufsize);
|
||||
COM_QuotedKeyVal("gamedir", p->gamedir, buf, bufsize);
|
||||
if (p->qhash)
|
||||
COM_QuotedKeyVal("qhash", p->qhash, buf, bufsize);
|
||||
if (p->priority!=PM_DEFAULTPRIORITY)
|
||||
COM_QuotedKeyVal("priority", va("%i", p->priority), buf, bufsize);
|
||||
if (p->arch)
|
||||
COM_QuotedKeyVal("arch", p->arch, buf, bufsize);
|
||||
|
||||
if (p->license)
|
||||
COM_QuotedKeyVal("license", p->license, buf, bufsize);
|
||||
if (p->website)
|
||||
COM_QuotedKeyVal("website", p->website, buf, bufsize);
|
||||
if (p->author)
|
||||
COM_QuotedKeyVal("author", p->author, buf, bufsize);
|
||||
if (p->description)
|
||||
COM_QuotedKeyVal("desc", p->description, buf, bufsize);
|
||||
if (p->previewimage)
|
||||
COM_QuotedKeyVal("preview", p->previewimage, buf, bufsize);
|
||||
if (p->filesize)
|
||||
COM_QuotedKeyVal("filesize", va("%"PRIu64, p->filesize), buf, bufsize);
|
||||
|
||||
if (p->fsroot == FS_BINARYPATH)
|
||||
COM_QuotedKeyVal("root", "bin", buf, bufsize);
|
||||
if (p->packprefix)
|
||||
COM_QuotedKeyVal("packprefix", p->packprefix, buf, bufsize);
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
safeswitch(dep->dtype)
|
||||
{
|
||||
case DEP_FILE: COM_QuotedKeyVal("file", dep->name, buf, bufsize); break;
|
||||
case DEP_CACHEFILE: COM_QuotedKeyVal("cachefile", dep->name, buf, bufsize); break;
|
||||
case DEP_MAP: COM_QuotedKeyVal("map", dep->name, buf, bufsize); break;
|
||||
case DEP_REQUIRE: COM_QuotedKeyVal("depend", dep->name, buf, bufsize); break;
|
||||
case DEP_CONFLICT: COM_QuotedKeyVal("conflict", dep->name, buf, bufsize); break;
|
||||
case DEP_REPLACE: COM_QuotedKeyVal("replace", dep->name, buf, bufsize); break;
|
||||
case DEP_FILECONFLICT: COM_QuotedKeyVal("fileconflict",dep->name, buf, bufsize); break;
|
||||
case DEP_RECOMMEND: COM_QuotedKeyVal("recommend", dep->name, buf, bufsize); break;
|
||||
case DEP_NEEDFEATURE: COM_QuotedKeyVal("need", dep->name, buf, bufsize); break;
|
||||
case DEP_SUGGEST: COM_QuotedKeyVal("suggest", dep->name, buf, bufsize); break;
|
||||
case DEP_SOURCE: COM_QuotedKeyVal("source", dep->name, buf, bufsize); break;
|
||||
case DEP_EXTRACTNAME: COM_QuotedKeyVal("unzipfile", dep->name, buf, bufsize); break;
|
||||
safedefault:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->flags & DPF_TESTING)
|
||||
COM_QuotedKeyVal("test", "1", buf, bufsize);
|
||||
|
||||
if ((p->flags & DPF_AUTOMARKED) && !(p->flags & DPF_USERMARKED))
|
||||
COM_QuotedKeyVal("auto", "1", buf, bufsize);
|
||||
|
||||
Q_strncatz(buf, "}", bufsize);
|
||||
Q_strncatz(buf, "\n", bufsize);
|
||||
}
|
||||
static void PM_WriteInstalledPackage_v2(package_t *p, char *buf, size_t bufsize)
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
|
||||
buf[0] = 0;
|
||||
COM_QuotedString(va("%s%s", p->category, p->name), buf, bufsize, false);
|
||||
if (p->flags & DPF_ENABLED)
|
||||
{ //v3+
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("enabled=1"), buf, bufsize);
|
||||
}
|
||||
else
|
||||
{ //v2
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("stale=1"), buf, bufsize);
|
||||
}
|
||||
if (p->flags & DPF_GUESSED)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("guessed=1"), buf, bufsize);
|
||||
}
|
||||
if (*p->title && strcmp(p->title, p->name))
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("title=%s", p->title), buf, bufsize);
|
||||
}
|
||||
if (*p->version)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("ver=%s", p->version), buf, bufsize);
|
||||
}
|
||||
//if (*p->gamedir)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("gamedir=%s", p->gamedir), buf, bufsize);
|
||||
}
|
||||
if (p->qhash)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("qhash=%s", p->qhash), buf, bufsize);
|
||||
}
|
||||
if (p->priority!=PM_DEFAULTPRIORITY)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("priority=%i", p->priority), buf, bufsize);
|
||||
}
|
||||
if (p->arch)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("arch=%s", p->arch), buf, bufsize);
|
||||
}
|
||||
|
||||
if (p->license)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("license=%s", p->license), buf, bufsize);
|
||||
}
|
||||
if (p->website)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("website=%s", p->website), buf, bufsize);
|
||||
}
|
||||
if (p->author)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("author=%s", p->author), buf, bufsize);
|
||||
}
|
||||
if (p->description)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("desc=%s", p->description), buf, bufsize);
|
||||
}
|
||||
if (p->previewimage)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("preview=%s", p->previewimage), buf, bufsize);
|
||||
}
|
||||
if (p->filesize)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("filesize=%"PRIu64, p->filesize), buf, bufsize);
|
||||
}
|
||||
|
||||
if (p->fsroot == FS_BINARYPATH)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat("root=bin", buf, bufsize);
|
||||
}
|
||||
if (p->packprefix)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("packprefix=%s", p->packprefix), buf, bufsize);
|
||||
}
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_FILE)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("file=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_CACHEFILE)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("cachefile=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_MAP)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("map=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_REQUIRE)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("depend=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_CONFLICT)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("conflict=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_REPLACE)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("replace=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_FILECONFLICT)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("fileconflict=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_RECOMMEND)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("recommend=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
else if (dep->dtype == DEP_NEEDFEATURE)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat(va("need=%s", dep->name), buf, bufsize);
|
||||
}
|
||||
}
|
||||
|
||||
if (p->flags & DPF_TESTING)
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat("test=1", buf, bufsize);
|
||||
}
|
||||
|
||||
if ((p->flags & DPF_AUTOMARKED) && !(p->flags & DPF_USERMARKED))
|
||||
{
|
||||
Q_strncatz(buf, " ", bufsize);
|
||||
COM_QuotedConcat("auto", buf, bufsize);
|
||||
}
|
||||
|
||||
buf[bufsize-2] = 0; //just in case.
|
||||
Q_strncatz(buf, "\n", bufsize);
|
||||
}
|
||||
static void PM_WriteInstalledPackages(void)
|
||||
{
|
||||
char buf[65536];
|
||||
int i;
|
||||
char *s;
|
||||
package_t *p;
|
||||
struct packagedep_s *dep;
|
||||
vfsfile_t *f = FS_OpenVFS(INSTALLEDFILES, "wb", FS_ROOT);
|
||||
qboolean v3 = false;
|
||||
if (!f)
|
||||
|
@ -3021,233 +3291,11 @@ static void PM_WriteInstalledPackages(void)
|
|||
{
|
||||
if (p->flags & (DPF_PRESENT|DPF_ENABLED))
|
||||
{
|
||||
buf[0] = 0;
|
||||
if (v3)
|
||||
{
|
||||
buf[0] = '{';
|
||||
buf[1] = '\n';
|
||||
buf[2] = 0;
|
||||
COM_QuotedKeyVal("package", p->name, buf, sizeof(buf));
|
||||
COM_QuotedKeyVal("category", p->category, buf, sizeof(buf));
|
||||
if (p->flags & DPF_ENABLED)
|
||||
COM_QuotedKeyVal("enabled", "1", buf, sizeof(buf));
|
||||
if (p->flags & DPF_GUESSED)
|
||||
COM_QuotedKeyVal("guessed", "1", buf, sizeof(buf));
|
||||
if (*p->title && strcmp(p->title, p->name))
|
||||
COM_QuotedKeyVal("title", p->title, buf, sizeof(buf));
|
||||
if (*p->version)
|
||||
COM_QuotedKeyVal("ver", p->version, buf, sizeof(buf));
|
||||
COM_QuotedKeyVal("gamedir", p->gamedir, buf, sizeof(buf));
|
||||
if (p->qhash)
|
||||
COM_QuotedKeyVal("qhash", p->qhash, buf, sizeof(buf));
|
||||
if (p->priority!=PM_DEFAULTPRIORITY)
|
||||
COM_QuotedKeyVal("priority", va("%i", p->priority), buf, sizeof(buf));
|
||||
if (p->arch)
|
||||
COM_QuotedKeyVal("arch", p->arch, buf, sizeof(buf));
|
||||
|
||||
if (p->license)
|
||||
COM_QuotedKeyVal("license", p->license, buf, sizeof(buf));
|
||||
if (p->website)
|
||||
COM_QuotedKeyVal("website", p->website, buf, sizeof(buf));
|
||||
if (p->author)
|
||||
COM_QuotedKeyVal("author", p->author, buf, sizeof(buf));
|
||||
if (p->description)
|
||||
COM_QuotedKeyVal("desc", p->description, buf, sizeof(buf));
|
||||
if (p->previewimage)
|
||||
COM_QuotedKeyVal("preview", p->previewimage, buf, sizeof(buf));
|
||||
if (p->filesize)
|
||||
COM_QuotedKeyVal("filesize", va("%"PRIu64, p->filesize), buf, sizeof(buf));
|
||||
|
||||
if (p->fsroot == FS_BINARYPATH)
|
||||
COM_QuotedKeyVal("root", "bin", buf, sizeof(buf));
|
||||
if (p->packprefix)
|
||||
COM_QuotedKeyVal("packprefix", p->packprefix, buf, sizeof(buf));
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_FILE)
|
||||
COM_QuotedKeyVal("file", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_CACHEFILE)
|
||||
COM_QuotedKeyVal("cachefile", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_MAP)
|
||||
COM_QuotedKeyVal("map", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_REQUIRE)
|
||||
COM_QuotedKeyVal("depend", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_CONFLICT)
|
||||
COM_QuotedKeyVal("conflict", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_REPLACE)
|
||||
COM_QuotedKeyVal("replace", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_FILECONFLICT)
|
||||
COM_QuotedKeyVal("fileconflict", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_RECOMMEND)
|
||||
COM_QuotedKeyVal("recommend", dep->name, buf, sizeof(buf));
|
||||
else if (dep->dtype == DEP_NEEDFEATURE)
|
||||
COM_QuotedKeyVal("need", dep->name, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
if (p->flags & DPF_TESTING)
|
||||
COM_QuotedKeyVal("test", "1", buf, sizeof(buf));
|
||||
|
||||
if ((p->flags & DPF_AUTOMARKED) && !(p->flags & DPF_USERMARKED))
|
||||
COM_QuotedKeyVal("auto", "1", buf, sizeof(buf));
|
||||
|
||||
Q_strncatz(buf, "}", sizeof(buf));
|
||||
}
|
||||
PM_WriteInstalledPackage_v3(p, buf, sizeof(buf));
|
||||
else
|
||||
{
|
||||
COM_QuotedString(va("%s%s", p->category, p->name), buf, sizeof(buf), false);
|
||||
if (p->flags & DPF_ENABLED)
|
||||
{ //v3+
|
||||
// Q_strncatz(buf, " ", sizeof(buf));
|
||||
// COM_QuotedConcat(va("enabled=1"), buf, sizeof(buf));
|
||||
}
|
||||
else
|
||||
{ //v2
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("stale=1"), buf, sizeof(buf));
|
||||
}
|
||||
if (p->flags & DPF_GUESSED)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("guessed=1"), buf, sizeof(buf));
|
||||
}
|
||||
if (*p->title && strcmp(p->title, p->name))
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("title=%s", p->title), buf, sizeof(buf));
|
||||
}
|
||||
if (*p->version)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("ver=%s", p->version), buf, sizeof(buf));
|
||||
}
|
||||
//if (*p->gamedir)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("gamedir=%s", p->gamedir), buf, sizeof(buf));
|
||||
}
|
||||
if (p->qhash)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("qhash=%s", p->qhash), buf, sizeof(buf));
|
||||
}
|
||||
if (p->priority!=PM_DEFAULTPRIORITY)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("priority=%i", p->priority), buf, sizeof(buf));
|
||||
}
|
||||
if (p->arch)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("arch=%s", p->arch), buf, sizeof(buf));
|
||||
}
|
||||
PM_WriteInstalledPackage_v2(p, buf, sizeof(buf));
|
||||
|
||||
if (p->license)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("license=%s", p->license), buf, sizeof(buf));
|
||||
}
|
||||
if (p->website)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("website=%s", p->website), buf, sizeof(buf));
|
||||
}
|
||||
if (p->author)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("author=%s", p->author), buf, sizeof(buf));
|
||||
}
|
||||
if (p->description)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("desc=%s", p->description), buf, sizeof(buf));
|
||||
}
|
||||
if (p->previewimage)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("preview=%s", p->previewimage), buf, sizeof(buf));
|
||||
}
|
||||
if (p->filesize)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("filesize=%"PRIu64, p->filesize), buf, sizeof(buf));
|
||||
}
|
||||
|
||||
if (p->fsroot == FS_BINARYPATH)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat("root=bin", buf, sizeof(buf));
|
||||
}
|
||||
if (p->packprefix)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("packprefix=%s", p->packprefix), buf, sizeof(buf));
|
||||
}
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_FILE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("file=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_CACHEFILE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("cachefile=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_MAP)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("map=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_REQUIRE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("depend=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_CONFLICT)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("conflict=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_REPLACE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("replace=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_FILECONFLICT)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("fileconflict=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_RECOMMEND)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("recommend=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_NEEDFEATURE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("need=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
if (p->flags & DPF_TESTING)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat("test=1", buf, sizeof(buf));
|
||||
}
|
||||
|
||||
if ((p->flags & DPF_AUTOMARKED) && !(p->flags & DPF_USERMARKED))
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat("auto", buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
buf[sizeof(buf)-2] = 0; //just in case.
|
||||
Q_strncatz(buf, "\n", sizeof(buf));
|
||||
VFS_WRITE(f, buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
|
@ -3644,8 +3692,11 @@ static void PM_Download_PreliminaryGot(struct dl_download *dl)
|
|||
for (info.p = availablepackages; info.p ; info.p=info.p->next)
|
||||
{
|
||||
if (info.p->download == dl)
|
||||
{
|
||||
info.p->download = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
info.successful = (dl->status == DL_FINISHED);
|
||||
if (dl->file)
|
||||
|
@ -3950,7 +4001,7 @@ static void PM_DownloadsCompleted(int iarg, void *data)
|
|||
Z_Free(pm_onload.package);
|
||||
pm_onload.package = NULL;
|
||||
COM_Gamedir(p->gamedir, packs);
|
||||
Cbuf_InsertText(va("map %s\n", map), RESTRICT_LOCAL, false);
|
||||
Cbuf_InsertText(map, RESTRICT_LOCAL, false);
|
||||
Z_Free(map);
|
||||
}
|
||||
else
|
||||
|
@ -4693,6 +4744,18 @@ void PM_Command_f(void)
|
|||
Z_Free(sorted);
|
||||
Con_Printf("<end of list>\n");
|
||||
}
|
||||
else if (!strcmp(act, "internal"))
|
||||
{
|
||||
char buf[65536];
|
||||
key = Cmd_Argv(2);
|
||||
for (p = availablepackages; p; p=p->next)
|
||||
{
|
||||
if (Q_strcasecmp(p->name, key))
|
||||
continue;
|
||||
PM_WriteInstalledPackage_v3(p, buf, sizeof(buf));
|
||||
Con_Printf("%s", buf);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(act, "show"))
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
|
@ -5028,6 +5091,7 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
|||
int idx;
|
||||
struct manpack_s *pack;
|
||||
const char *baseurl = man->updateurl; //this is a url for updated versions of the fmf itself.
|
||||
int dtype;
|
||||
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
p->flags &= ~DPF_MANIMARKED;
|
||||
|
@ -5047,6 +5111,20 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
|||
continue; //ignore it
|
||||
}
|
||||
|
||||
if (pack->mirrors[0])
|
||||
{
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
{
|
||||
if (p->mirror[0] && !strcmp(p->mirror[0], pack->mirrors[0]))
|
||||
break;
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
PM_MarkPackage(p, DPF_MANIMARKED);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
p = Z_Malloc(sizeof(*p));
|
||||
p->name = Z_StrDup(pack->path);
|
||||
p->title = Z_StrDup(pack->path);
|
||||
|
@ -5056,6 +5134,7 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
|||
strcpy(p->version, "");
|
||||
p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED;
|
||||
p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL;
|
||||
dtype = DEP_FILE;
|
||||
|
||||
//note that this signs the hash(validated with size) with an separately trusted authority and is thus not dependant upon trusting the manifest itself...
|
||||
//that said, we can't necessarily trust any overrides the manifest might include - those parts do not form part of the signature.
|
||||
|
@ -5129,7 +5208,7 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
|||
if (url && *url)
|
||||
p->mirror[i] = Z_StrDup(url);
|
||||
}
|
||||
PM_AddDep(p, DEP_FILE, path);
|
||||
PM_AddDep(p, dtype, path);
|
||||
|
||||
PM_ValidateAuthenticity(p, VH_UNSUPPORTED);
|
||||
|
||||
|
@ -5289,6 +5368,8 @@ typedef struct {
|
|||
int downloadablessequence;
|
||||
char titletext[128];
|
||||
char applymessage[128]; //so we can change its text to give it focus
|
||||
char filtertext[128];
|
||||
qboolean filtering;
|
||||
const void *expandedpackage; //which package we're currently viewing maps for.
|
||||
qboolean populated;
|
||||
} dlmenu_t;
|
||||
|
@ -5594,12 +5675,14 @@ static qboolean MD_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsi
|
|||
|
||||
static void MD_MapDraw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
|
||||
{
|
||||
const package_t *p = c->dptr;
|
||||
struct packagedep_s *map = c->dptr2;
|
||||
#if defined(HAVE_SERVER)
|
||||
const package_t *p = c->dptr;
|
||||
struct packagedep_s *dep;
|
||||
float besttime, fulltime, bestkills, bestsecrets;
|
||||
char *package = NULL;
|
||||
const char *ext;
|
||||
#endif
|
||||
|
||||
if (y + 8 < 0 || y >= vid.height) //small optimisation.
|
||||
return;
|
||||
|
@ -5607,7 +5690,7 @@ static void MD_MapDraw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
|
|||
if (c->dint != downloadablessequence)
|
||||
return; //probably stale
|
||||
|
||||
|
||||
#if defined(HAVE_SERVER)
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_CACHEFILE)
|
||||
|
@ -5627,6 +5710,7 @@ static void MD_MapDraw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
|
|||
Draw_FunStringU8(CON_WHITEMASK, x+48+8*4, y, va("^m%s^m (%g %g in %.1f secs)", map->name, bestkills,bestsecrets,fulltime));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
Draw_FunStringU8(CON_WHITEMASK, x+48+8*4, y, map->name);
|
||||
}
|
||||
static qboolean MD_MapKey (struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode)
|
||||
|
@ -5825,7 +5909,7 @@ static qboolean MD_RevertUpdates (union menuoption_s *mo,struct emenu_s *m,int k
|
|||
return false;
|
||||
}
|
||||
|
||||
static int MD_AddMapItems(emenu_t *m, package_t *p, int y)
|
||||
static int MD_AddMapItems(emenu_t *m, package_t *p, int y, const char *filter)
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
menucustom_t *c;
|
||||
|
@ -5833,6 +5917,9 @@ static int MD_AddMapItems(emenu_t *m, package_t *p, int y)
|
|||
{
|
||||
if (dep->dtype != DEP_MAP)
|
||||
continue;
|
||||
if (filter)
|
||||
if (!strstr(dep->name, filter))
|
||||
continue;
|
||||
c = MC_AddCustom(m, 0, y, p, downloadablessequence, NULL);
|
||||
c->dptr2 = dep;
|
||||
c->draw = MD_MapDraw;
|
||||
|
@ -5843,7 +5930,37 @@ static int MD_AddMapItems(emenu_t *m, package_t *p, int y)
|
|||
}
|
||||
return y;
|
||||
}
|
||||
static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix, void *selpackage)
|
||||
static int MD_DownloadMenuFiltered(package_t *p, const char *filter)
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
if ((p->flags & DPF_HIDDEN) && (p->arch || !(p->flags & DPF_ENABLED)))
|
||||
return true;
|
||||
if ((p->flags & DPF_HIDEUNLESSPRESENT) && !(p->flags & DPF_PRESENT))
|
||||
return true;
|
||||
|
||||
if (filter && *filter)
|
||||
{
|
||||
if (strstr(p->title, filter) ||
|
||||
strstr(p->name, filter) ||
|
||||
(p->description && strstr(p->description, filter)) ||
|
||||
(p->author && strstr(p->author, filter)))
|
||||
;
|
||||
else
|
||||
{
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_MAP)
|
||||
if (strstr(dep->name, filter))
|
||||
return -1;
|
||||
}
|
||||
if (!dep)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix, const char *filter, void *selpackage)
|
||||
{
|
||||
char path[MAX_QPATH];
|
||||
package_t *p;
|
||||
|
@ -5853,15 +5970,15 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix,
|
|||
int prefixlen = strlen(pathprefix);
|
||||
struct packagedep_s *dep;
|
||||
dlmenu_t *info = m->data;
|
||||
int filtered;
|
||||
|
||||
//add all packages in this dir
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
{
|
||||
if (strncmp(p->category, pathprefix, prefixlen))
|
||||
continue;
|
||||
if ((p->flags & DPF_HIDDEN) && (p->arch || !(p->flags & DPF_ENABLED)))
|
||||
continue;
|
||||
if ((p->flags & DPF_HIDEUNLESSPRESENT) && !(p->flags & DPF_PRESENT))
|
||||
filtered = MD_DownloadMenuFiltered(p, filter);
|
||||
if (filtered==true)
|
||||
continue;
|
||||
slash = strchr(p->category+prefixlen, '/');
|
||||
if (!slash)
|
||||
|
@ -5926,11 +6043,11 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix,
|
|||
c->common.height = 8;
|
||||
y += 8;
|
||||
|
||||
if (info->expandedpackage == p)
|
||||
if (info->expandedpackage == p || filtered<0)
|
||||
{
|
||||
m->selecteditem = (menuoption_t*)c;
|
||||
|
||||
y = MD_AddMapItems(m, p, y);
|
||||
y = MD_AddMapItems(m, p, y, (filtered==-1)?filter:NULL);
|
||||
}
|
||||
if (!m->selecteditem || p == selpackage)
|
||||
m->selecteditem = (menuoption_t*)c;
|
||||
|
@ -5942,9 +6059,7 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix,
|
|||
{
|
||||
if (strncmp(p->category, pathprefix, prefixlen))
|
||||
continue;
|
||||
if ((p->flags & DPF_HIDDEN) && (p->arch || !(p->flags & DPF_ENABLED)))
|
||||
continue;
|
||||
if ((p->flags & DPF_HIDEUNLESSPRESENT) && !(p->flags & DPF_PRESENT))
|
||||
if (MD_DownloadMenuFiltered(p, filter)==true)
|
||||
continue;
|
||||
|
||||
slash = strchr(p->category+prefixlen, '/');
|
||||
|
@ -5965,7 +6080,7 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix,
|
|||
MC_AddBufferedText(m, 48, 320-16, y, path+prefixlen, false, true);
|
||||
y += 8;
|
||||
Q_strncatz(path, "/", sizeof(path));
|
||||
y = MD_AddItemsToDownloadMenu(m, y, path, selpackage);
|
||||
y = MD_AddItemsToDownloadMenu(m, y, path, filter, selpackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6008,6 +6123,8 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
|
|||
|
||||
info->populated = false;
|
||||
MC_AddWhiteText(m, 24, 320, 8, "Downloads", false)->text = info->titletext;
|
||||
if (info->filtering || *info->filtertext)
|
||||
MC_AddWhiteText(m, 24, 320, 16, va("%sFilter: %s", info->filtering?"^m":"", info->filtertext), false);
|
||||
MC_AddWhiteText(m, 16, 320, 24, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f", false);
|
||||
|
||||
//FIXME: should probably reselect the previous selected item. lets just assume everyone uses a mouse...
|
||||
|
@ -6080,6 +6197,8 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
|
|||
|
||||
info->populated = true;
|
||||
MC_AddFrameStart(m, 48);
|
||||
if (!info->filtering)
|
||||
{
|
||||
#ifdef WEBCLIENT
|
||||
for (i = 0, sources=false; i < pm_numsources; i++)
|
||||
{
|
||||
|
@ -6133,10 +6252,15 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
|
|||
}
|
||||
#endif
|
||||
y+=4; //small gap
|
||||
}
|
||||
else d = NULL;
|
||||
MC_AddBufferedText(m, 48, 320-16, y, "Packages", false, true), y += 8;
|
||||
MD_AddItemsToDownloadMenu(m, y, info->pathprefix, oldpackage);
|
||||
MD_AddItemsToDownloadMenu(m, y, info->pathprefix, info->filtertext, oldpackage);
|
||||
if (!m->selecteditem)
|
||||
m->selecteditem = (menuoption_t*)d;
|
||||
if (info->filtering)
|
||||
m->cursoritem = NULL;
|
||||
else
|
||||
m->cursoritem = (menuoption_t*)MC_AddWhiteText(m, 40, 0, m->selecteditem->common.posy, NULL, false);
|
||||
MC_AddFrameEnd(m, 48)->frac = framefrac;
|
||||
}
|
||||
|
@ -6156,6 +6280,57 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
|
|||
}
|
||||
}
|
||||
|
||||
static qboolean MD_Download_Key(struct emenu_s *m, int key, unsigned int unicode)
|
||||
{
|
||||
dlmenu_t *info = m->data;
|
||||
|
||||
if (info->filtering)
|
||||
{
|
||||
if (key == K_BACKSPACE)
|
||||
{
|
||||
unsigned int l = strlen(info->filtertext);
|
||||
if (l)
|
||||
{
|
||||
while (l > 0 && (info->filtertext[--l]&0xc0) == 0x80)
|
||||
;
|
||||
info->filtertext[l] = 0;
|
||||
}
|
||||
else
|
||||
info->filtering = false;
|
||||
}
|
||||
else if (key == K_ENTER || key == K_ESCAPE)
|
||||
info->filtering = false; //done...
|
||||
else if (key>=K_F1 && key!=K_RALT && key!=K_RCTRL && key!=K_RSHIFT)
|
||||
{ //some other action... don't swallow clicks.
|
||||
info->filtering = false;
|
||||
info->populated = false;
|
||||
return false;
|
||||
}
|
||||
else if (unicode)
|
||||
{
|
||||
unsigned int l = strlen(info->filtertext);
|
||||
l+=utf8_encode(info->filtertext+l, unicode, sizeof(info->filtertext)-1-l);
|
||||
info->filtertext[l] = 0;
|
||||
}
|
||||
|
||||
info->populated = false;
|
||||
return true;
|
||||
}
|
||||
else if (key == '/')
|
||||
{
|
||||
info->filtering = true;
|
||||
info->filtertext[0] = 0;
|
||||
|
||||
info->populated = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->filtering = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Menu_DownloadStuff_f (void)
|
||||
{
|
||||
emenu_t *menu;
|
||||
|
@ -6167,6 +6342,7 @@ void Menu_DownloadStuff_f (void)
|
|||
|
||||
menu->menu.persist = true;
|
||||
menu->predraw = MD_Download_UpdateStatus;
|
||||
menu->key = MD_Download_Key;
|
||||
info->downloadablessequence = downloadablessequence;
|
||||
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ int dotofs;
|
|||
|
||||
static void MenuTooltipChange(emenu_t *menu, const char *text)
|
||||
{
|
||||
unsigned int MAX_CHARS=1024;
|
||||
unsigned int MAX_CHARS=2048;
|
||||
menutooltip_t *mtt;
|
||||
if (menu->tooltip)
|
||||
{
|
||||
|
@ -2081,13 +2081,14 @@ menuoption_t *M_PrevSelectableItem(emenu_t *m, menuoption_t *old, qboolean wrap)
|
|||
|
||||
void M_Complex_Key(emenu_t *currentmenu, int key, int unicode)
|
||||
{
|
||||
menuoption_t *mi;
|
||||
if (!currentmenu)
|
||||
return; //erm...
|
||||
|
||||
M_CheckMouseMove(currentmenu);
|
||||
|
||||
if (currentmenu->key)
|
||||
if (currentmenu->key(key, currentmenu))
|
||||
if (currentmenu->key(currentmenu, key, unicode))
|
||||
return;
|
||||
|
||||
if (currentmenu->selecteditem && currentmenu->selecteditem->common.type == mt_custom && (key == K_DOWNARROW || key == K_KP_DOWNARROW || key == K_GP_DPAD_DOWN || key == K_GP_LEFT_THUMB_DOWN || key == K_GP_DIAMOND_CONFIRM || key == K_GP_DIAMOND_ALTCONFIRM || key == K_UPARROW || key == K_KP_UPARROW || key == K_GP_DPAD_UP || key == K_GP_LEFT_THUMB_UP || key == K_TAB || key == K_MWHEELUP || key == K_MWHEELDOWN || key == K_PGUP || key == K_PGDN))
|
||||
|
@ -2206,28 +2207,31 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode)
|
|||
|
||||
case K_MWHEELUP:
|
||||
case K_MWHEELDOWN:
|
||||
if (currentmenu->mouseitem)
|
||||
mi = currentmenu->mouseitem;
|
||||
if (!mi)
|
||||
mi = currentmenu->selecteditem;
|
||||
if (mi)
|
||||
{
|
||||
qboolean handled = false;
|
||||
switch(currentmenu->mouseitem->common.type)
|
||||
switch(mi->common.type)
|
||||
{
|
||||
case mt_combo:
|
||||
if (mousecursor_x >= currentmenu->xpos + currentmenu->mouseitem->common.posx + currentmenu->mouseitem->combo.captionwidth + 3*8)
|
||||
if (mousecursor_x >= currentmenu->xpos + mi->common.posx + mi->combo.captionwidth + 3*8)
|
||||
{
|
||||
MC_Combo_Key(¤tmenu->mouseitem->combo, key);
|
||||
MC_Combo_Key(&mi->combo, key);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case mt_checkbox:
|
||||
if (mousecursor_x >= currentmenu->xpos + currentmenu->mouseitem->common.posx + currentmenu->mouseitem->check.textwidth + 3*8)
|
||||
if (mousecursor_x >= currentmenu->xpos + mi->common.posx + mi->check.textwidth + 3*8)
|
||||
{
|
||||
MC_CheckBox_Key(¤tmenu->mouseitem->check, currentmenu, key);
|
||||
MC_CheckBox_Key(&mi->check, currentmenu, key);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case mt_custom:
|
||||
if (currentmenu->mouseitem->custom.key)
|
||||
handled = currentmenu->mouseitem->custom.key(¤tmenu->mouseitem->custom, currentmenu, key, unicode);
|
||||
if (mi->custom.key)
|
||||
handled = mi->custom.key(&mi->custom, currentmenu, key, unicode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2235,7 +2239,7 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode)
|
|||
|
||||
if (handled)
|
||||
{
|
||||
currentmenu->selecteditem = currentmenu->mouseitem;
|
||||
currentmenu->selecteditem = mi;
|
||||
if (currentmenu->cursoritem)
|
||||
currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy + (currentmenu->selecteditem->common.height-currentmenu->cursoritem->common.height)/2;
|
||||
break;
|
||||
|
@ -2326,7 +2330,7 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode)
|
|||
|
||||
|
||||
|
||||
qboolean MC_Main_Key (int key, emenu_t *menu) //here purly to restart demos.
|
||||
qboolean MC_Main_Key (emenu_t *menu, int key, unsigned int unicode) //here purly to restart demos.
|
||||
{
|
||||
if (key == K_ESCAPE || key == K_GP_BACK || key == K_GP_DIAMOND_CANCEL || key == K_MOUSE2)
|
||||
{
|
||||
|
|
|
@ -765,7 +765,7 @@ static void SL_PostDraw (emenu_t *menu)
|
|||
}
|
||||
}
|
||||
}
|
||||
static qboolean SL_Key (int key, emenu_t *menu)
|
||||
static qboolean SL_Key (emenu_t *menu, int key, unsigned int unicode)
|
||||
{
|
||||
serverlist_t *info = (serverlist_t*)(menu + 1);
|
||||
|
||||
|
@ -1370,7 +1370,7 @@ static void M_QuickConnect_PreDraw(emenu_t *menu)
|
|||
}
|
||||
}
|
||||
|
||||
static qboolean M_QuickConnect_Key (int key, emenu_t *menu)
|
||||
static qboolean M_QuickConnect_Key (emenu_t *menu, int key, unsigned int unicode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1183,7 +1183,7 @@ void Com_CompleateOSFileName(char *name)
|
|||
strcpy(name, compleatenamename);
|
||||
}
|
||||
|
||||
qboolean M_Media_Key (int key, emenu_t *menu)
|
||||
qboolean M_Media_Key (emenu_t *menu, int key, unsigned int unicode)
|
||||
{
|
||||
int dir;
|
||||
if (key == K_ESCAPE || key == K_GP_BACK || key == K_MOUSE2)
|
||||
|
|
|
@ -449,7 +449,7 @@ typedef struct {
|
|||
soundcardinfo_t *card;
|
||||
} audiomenuinfo_t;
|
||||
|
||||
qboolean M_Audio_Key (int key, struct emenu_s *menu)
|
||||
qboolean M_Audio_Key (struct emenu_s *menu, int key, unsigned int unicode)
|
||||
{
|
||||
int i;
|
||||
audiomenuinfo_t *info = menu->data;
|
||||
|
|
|
@ -57,7 +57,7 @@ void M_Script_Remove (emenu_t *menu)
|
|||
|
||||
M_Script_Option(menu, "cancel", false);
|
||||
}
|
||||
qboolean M_Script_Key (int key, emenu_t *menu)
|
||||
qboolean M_Script_Key (struct emenu_s *menu, int key, unsigned int unicode)
|
||||
{
|
||||
if (menu->selecteditem && menu->selecteditem->common.type == mt_edit)
|
||||
return false;
|
||||
|
|
|
@ -1081,7 +1081,7 @@ void M_Help_Draw (emenu_t *m)
|
|||
R2D_ScalePic ((vid.width-width)/2, (vid.height-height)/2, width, height, pic);
|
||||
}
|
||||
}
|
||||
qboolean M_Help_Key (int key, emenu_t *m)
|
||||
qboolean M_Help_Key (struct emenu_s *m, int key, unsigned int unicode)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
|
|
|
@ -329,7 +329,7 @@ struct emenu_s {
|
|||
|
||||
void (*reset) (struct emenu_s *); //called after a video mode switch / shader reload.
|
||||
void (*remove) (struct emenu_s *);
|
||||
qboolean (*key) (int key, struct emenu_s *); //true if key was handled
|
||||
qboolean (*key) (struct emenu_s *, int key, unsigned int unicode); //true if key was handled
|
||||
void (*predraw) (struct emenu_s *);
|
||||
void (*postdraw) (struct emenu_s *);
|
||||
menuoption_t *options;
|
||||
|
|
|
@ -789,7 +789,7 @@ typedef struct
|
|||
} gamepath[8];
|
||||
struct manpack_s //FIXME: this struct should be replaced with packagemanager info instead.
|
||||
{
|
||||
int type;
|
||||
enum manifestdeptype_e type;
|
||||
char *path; //the 'pure' name
|
||||
char *prefix;
|
||||
qboolean crcknown; //if the crc was specified
|
||||
|
|
|
@ -4896,6 +4896,8 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!FS_GamedirIsOkay(dir))
|
||||
continue;
|
||||
FS_AddGameDirectory(&oldpaths, dir, reloadflags, fl);
|
||||
}
|
||||
}
|
||||
|
@ -4912,15 +4914,6 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
char *dir = fs_manifest->gamepath[i].path;
|
||||
if (dir && !(fs_manifest->gamepath[i].flags&GAMEDIR_BASEGAME))
|
||||
{
|
||||
//don't allow leading dots, hidden files are evil.
|
||||
//don't allow complex paths. those are evil too.
|
||||
if (!*dir || *dir == '.' || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/")
|
||||
|| strstr(dir, "\\") || strstr(dir, ":") )
|
||||
{
|
||||
Con_Printf ("Gamedir should be a single filename, not a path\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < countof(fs_manifest->gamepath); j++)
|
||||
{
|
||||
char *dir2 = fs_manifest->gamepath[j].path;
|
||||
|
@ -4930,12 +4923,28 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
if (j < countof(fs_manifest->gamepath))
|
||||
continue; //already loaded above. don't mess up gameonly_gamedir.
|
||||
|
||||
fl = SPF_EXPLICIT;
|
||||
if (!(fs_manifest->gamepath[i].flags&GAMEDIR_READONLY))
|
||||
fl |= SPF_WRITABLE;
|
||||
if (fs_manifest->gamepath[i].flags&GAMEDIR_PRIVATE)
|
||||
fl |= SPF_PRIVATE;
|
||||
if (fs_manifest->gamepath[i].flags&GAMEDIR_QSHACK)
|
||||
fl |= SPF_QSHACK;
|
||||
|
||||
if (*dir == '*')
|
||||
{
|
||||
{ //just in case... shouldn't be needed.
|
||||
dir++;
|
||||
fl |= GAMEDIR_PRIVATE;
|
||||
}
|
||||
|
||||
if (fs_manifest->gamepath[i].flags & GAMEDIR_SPECIAL)
|
||||
; //don't.
|
||||
else
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, dir, reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
|
||||
//don't use evil gamedir names.
|
||||
if (!FS_GamedirIsOkay(dir))
|
||||
continue;
|
||||
FS_AddGameDirectory(&oldpaths, dir, reloadflags, fl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7259,6 +7268,7 @@ static void FS_ChangeMod_f(void)
|
|||
int packages = 0;
|
||||
const char *arg = "?";
|
||||
qboolean okay = false;
|
||||
char *dir = NULL;
|
||||
|
||||
if (Cmd_IsInsecure())
|
||||
return;
|
||||
|
@ -7302,6 +7312,11 @@ static void FS_ChangeMod_f(void)
|
|||
arg = Cmd_Argv(i++);
|
||||
packagespaths[packages-1].subpath = Z_StrDup(arg);
|
||||
}
|
||||
else if (!strcmp(arg, "dir"))
|
||||
{
|
||||
arg = Cmd_Argv(i++);
|
||||
Z_StrDupPtr(&dir, arg);
|
||||
}
|
||||
else if (!strcmp(arg, "map"))
|
||||
{
|
||||
Z_Free(fs_loadedcommand);
|
||||
|
@ -7324,13 +7339,14 @@ static void FS_ChangeMod_f(void)
|
|||
}
|
||||
|
||||
if (okay)
|
||||
COM_Gamedir("", packagespaths);
|
||||
COM_Gamedir(dir?dir:"", packagespaths);
|
||||
else
|
||||
{
|
||||
Con_Printf("unsupported args: %s\n", arg);
|
||||
Z_Free(fs_loadedcommand);
|
||||
fs_loadedcommand = NULL;
|
||||
}
|
||||
Z_Free(dir);
|
||||
|
||||
for (i = 0; i < packages; i++)
|
||||
{
|
||||
|
|
|
@ -90,7 +90,7 @@ void Menu_Download_Update(void);
|
|||
typedef struct
|
||||
{
|
||||
char *description;
|
||||
void (*Update) (const char *url, vfsfile_t *out);
|
||||
void (*Update) (const char *url, vfsfile_t *out, qboolean favourcache);
|
||||
#define plugupdatesourcefuncs_name "UpdateSource"
|
||||
} plugupdatesourcefuncs_t;
|
||||
qboolean PM_RegisterUpdateSource(void *module, plugupdatesourcefuncs_t *funcs);
|
||||
|
|
|
@ -971,6 +971,7 @@ static qhandle_t QDECL Plug_FS_Open(const char *fname, qhandle_t *outhandle, int
|
|||
#ifndef WEBCLIENT
|
||||
f = NULL;
|
||||
#else
|
||||
Con_DPrintf("Plugin %s requesting %s\n", currentplug->name, fname);
|
||||
handle = Plug_NewStreamHandle(STREAM_WEB);
|
||||
pluginstreamarray[handle].dl = HTTP_CL_Get(fname, NULL, Plug_DownloadComplete);
|
||||
pluginstreamarray[handle].dl->user_num = handle;
|
||||
|
|
|
@ -1570,7 +1570,10 @@ void DL_Close(struct dl_download *dl)
|
|||
#ifdef MULTITHREAD
|
||||
dl->threadenable = false;
|
||||
if (dl->threadctx)
|
||||
{
|
||||
Sys_WaitOnThread(dl->threadctx);
|
||||
dl->threadctx = NULL;
|
||||
}
|
||||
#endif
|
||||
if (dl->file && dl->file->seekstyle < SS_PIPE)
|
||||
VFS_SEEK(dl->file, 0);
|
||||
|
|
|
@ -136,7 +136,7 @@ struct dl_download
|
|||
/*not used internally by the backend, but used by HTTP_CL_Get/thread wrapper*/
|
||||
struct dl_download *next;
|
||||
qboolean (*notifystarted) (struct dl_download *dl, char *mimetype); //mime can be null for some protocols, read dl->totalsize for size. false if the mime just isn't acceptable.
|
||||
void (*notifycomplete) (struct dl_download *dl);
|
||||
void (*notifycomplete) (struct dl_download *dl); //lets the requester know that the download context is complete and the handle is no longer valid.
|
||||
};
|
||||
|
||||
vfsfile_t *VFSPIPE_Open(int refs, qboolean seekable); //refs should be 1 or 2, to say how many times it must be closed before its actually closed, so both ends can close separately
|
||||
|
|
|
@ -730,7 +730,7 @@ void SV_Map_f (void)
|
|||
sv.mapchangelocked = false;
|
||||
}
|
||||
else
|
||||
PM_LoadMap(mangled, sep);
|
||||
PM_LoadMap(mangled, va("%s %s\n", Cmd_Argv(0), COM_QuotedString(sep, expanded, sizeof(expanded), false)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1003,7 +1003,10 @@ void SV_Map_f (void)
|
|||
if (!isrestart)
|
||||
{
|
||||
if (q3singleplayer)
|
||||
{
|
||||
Cvar_ForceSet(gametype, "2");//singleplayer
|
||||
Cvar_ForceSet(&deathmatch, "0");//for non-q3 type stuff to not get confused..
|
||||
}
|
||||
else if (gametype->value == 2)
|
||||
Cvar_ForceSet(gametype, "");//force to ffa deathmatch
|
||||
}
|
||||
|
|
|
@ -516,6 +516,8 @@ static void QI_AddPackages(xmltree_t *qifile)
|
|||
}
|
||||
static void QI_RunMap(xmltree_t *qifile, const char *map)
|
||||
{
|
||||
char gamedir[65];
|
||||
char buf[256];
|
||||
if (!qifile)
|
||||
{
|
||||
return;
|
||||
|
@ -527,10 +529,35 @@ static void QI_RunMap(xmltree_t *qifile, const char *map)
|
|||
if (!*map || strchr(map, '\\') || strchr(map, '\"') || strchr(map, '\n') || strchr(map, ';'))
|
||||
map = "";
|
||||
|
||||
strcpy(gamedir, "id1");
|
||||
{
|
||||
char descbuf[1024];
|
||||
xmltree_t *tech = XML_ChildOfTree(qifile, "techinfo", 0);
|
||||
const char *cmdline = XML_GetChildBody(tech, "commandline", "");
|
||||
while (cmdline)
|
||||
{
|
||||
cmdline = cmdfuncs->ParseToken(cmdline, descbuf, sizeof(descbuf), NULL);
|
||||
if (!strcmp(descbuf, "-game"))
|
||||
cmdline = cmdfuncs->ParseToken(cmdline, gamedir, sizeof(gamedir), NULL);
|
||||
else if (!strcmp(descbuf, "-hipnotic") || !strcmp(descbuf, "-rogue") || !strcmp(descbuf, "-quoth"))
|
||||
{
|
||||
if (!*gamedir)
|
||||
strcpy(gamedir, descbuf+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmdfuncs->AddText("fs_changemod spmap \"", false);
|
||||
cmdfuncs->AddText(map, false);
|
||||
cmdfuncs->AddText("\"", false);
|
||||
cmdfuncs->AddText("fs_changemod", false);
|
||||
if (*gamedir)
|
||||
{
|
||||
cmdfuncs->AddText(" dir ", false);
|
||||
cmdfuncs->AddText(cmdfuncs->QuotedString(gamedir, buf, sizeof(buf), false), false);
|
||||
}
|
||||
if (map && *map)
|
||||
{
|
||||
cmdfuncs->AddText(" spmap ", false);
|
||||
cmdfuncs->AddText(cmdfuncs->QuotedString(map, buf, sizeof(buf), false), false);
|
||||
}
|
||||
QI_AddPackages(qifile);
|
||||
// Con_Printf("Command: %s\n", cmd);
|
||||
cmdfuncs->AddText("\n", false);
|
||||
|
@ -548,13 +575,13 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, const char *format, ...)
|
|||
|
||||
VFS_PUTS(vf, string);
|
||||
}
|
||||
static void QI_WriteUpdateList(vfsfile_t *pminfo)
|
||||
static void QI_WriteUpdateList(xmltree_t *database, vfsfile_t *pminfo)
|
||||
{
|
||||
xmltree_t *file;
|
||||
char descbuf[1024], *d, *nl;
|
||||
|
||||
if (thedatabase)
|
||||
for (file = thedatabase->child; file; file = file->sibling)
|
||||
if (database)
|
||||
for (file = database->child; file; file = file->sibling)
|
||||
{
|
||||
const char *id = XML_GetParameter(file, "id", "unnamed");
|
||||
const char *rating = XML_GetParameter(file, "rating", "");
|
||||
|
@ -937,7 +964,7 @@ static void QDECL QI_Tick(double realtime, double gametime)
|
|||
else
|
||||
{
|
||||
VFS_PRINTF(packagemanager, "version 3\n");
|
||||
QI_WriteUpdateList(packagemanager);
|
||||
QI_WriteUpdateList(thedatabase, packagemanager);
|
||||
}
|
||||
VFS_CLOSE(packagemanager);
|
||||
packagemanager = NULL;
|
||||
|
@ -981,8 +1008,48 @@ static void QI_ExecuteCommand_f(void)
|
|||
QI_RefreshMapList(true);
|
||||
}
|
||||
|
||||
void QI_GenPackages(const char *url, vfsfile_t *pipe)
|
||||
void QI_GenPackages(const char *url, vfsfile_t *pipe, qboolean favourcache)
|
||||
{
|
||||
if (thedatabase)
|
||||
{ //already read it?... fine.
|
||||
VFS_PRINTF(pipe, "version 3\n");
|
||||
QI_WriteUpdateList(thedatabase, pipe);
|
||||
VFS_CLOSE(pipe);
|
||||
return;
|
||||
}
|
||||
else if (favourcache)
|
||||
{ //just read the cached copy from disk. use the menu to update it.
|
||||
xmltree_t *t = NULL;
|
||||
qhandle_t fd = -1;
|
||||
int ofs = 0;
|
||||
|
||||
int flen = filefuncs->Open("**plugconfig", &fd, 1);
|
||||
if (flen >= 0)
|
||||
{
|
||||
qbyte *file = malloc(flen+1);
|
||||
file[flen] = 0;
|
||||
filefuncs->Read(fd, file, flen);
|
||||
filefuncs->Close(fd);
|
||||
|
||||
do
|
||||
{
|
||||
if (t)
|
||||
XML_Destroy(t);
|
||||
t = XML_Parse(file, &ofs, flen, false, "");
|
||||
} while(t && !t->child);
|
||||
free(file);
|
||||
|
||||
VFS_PRINTF(pipe, "version 3\n");
|
||||
QI_WriteUpdateList(t, pipe);
|
||||
|
||||
if (t)
|
||||
XML_Destroy(t);
|
||||
VFS_CLOSE(pipe);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//fill it in once we've got it...
|
||||
if (packagemanager)
|
||||
VFS_CLOSE(packagemanager);
|
||||
packagemanager = pipe;
|
||||
|
|
Loading…
Reference in a new issue