quakeforge/ruamoko/cl_menu/plistmenu.r
Bill Currie 54f2e417dc [ruamoko] Fix daft str_str abi
Returning a string was a bad idea as it makes str_str difficult to use
with str_mid. (actually, iirc, it was the only reason I moved all
strings into progs memory... hmm).
2020-04-08 21:54:41 +09:00

190 lines
4.5 KiB
R

/*
plistmenu.r
PropertyList menu parser.
Copyright (C) 2010 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#include "debug.h"
#include "legacy_string.h"
#include "string.h"
#include "qfs.h"
#include "Array.h"
#include "gui/Rect.h"
#include "plistmenu.h"
@reference Pic;
@reference CenterPic;
@static @param
class_from_plist (PLDictionary *pldict)
{
local @param params[8];
local @param ret;
local @va_list va_list = { 0, params };
local string classname, selname, paramstr;
local id class;
local id obj;
local PLArray *messages, *msg;
local int message_count, i, j;
local SEL sel;
local PLItem *item;
ret = nil;
classname = [(PLString*) [pldict getObjectForKey:"Class"] string];
class = obj_lookup_class (classname);
if (!class) {
dprint ("could not find " + classname + "\n");
ret.pointer_val = nil;
return ret;
}
obj = [class alloc];
params[0].pointer_val = obj;
messages = (PLArray*) [pldict getObjectForKey:"Messages"];
message_count = [messages count];
for (i = 0; i < message_count; i++) {
msg = (PLArray*) [messages getObjectAtIndex:i];
selname = [(PLString*) [msg getObjectAtIndex:0] string];
sel = sel_get_uid (selname);
params[1].pointer_val = sel;
va_list.count = [msg count] + 1;
for (j = 2; j < va_list.count; j++) {
paramstr = [(PLString*) [msg getObjectAtIndex:j - 1] string];
switch (str_mid (paramstr, 0, 1)) {
case "\"":
va_list.list[j].string_val = str_mid (paramstr, 1, -1);
break;
case "$":
item = [pldict getObjectForKey:str_mid (paramstr, 1)];
va_list.list[j] = object_from_plist (item);
break;
case "0": case "1": case "2": case "3": case "4":
case "5": case "6": case "7": case "8": case "9":
if (str_str (paramstr, ".") >= 0)
va_list.list[j].float_val = stof (paramstr);
else
va_list.list[j].integer_val = stoi (paramstr);
break;
}
}
obj_msg_sendv (obj, sel, va_list);
}
ret.pointer_val = obj;
return ret;
}
@static @param
array_from_plist (PLArray *plarray)
{
local Array *array;
local int i, count;
local @param ret;
ret = nil;
array = [[Array alloc] init];
count = [plarray count];
for (i = 0; i < count; i++) {
ret = object_from_plist ([plarray getObjectAtIndex:i]);
[array addObject: (id) ret.pointer_val];
}
ret.pointer_val = array;
return ret;
}
union ParamRect {
@param p;
Rect r;
};
@static @param
rect_from_plist (PLString *plstring)
{
local string str = [plstring string];
local string tmp;
local int xp, yp, xl, yl;
local PLItem *item;
local union ParamRect pr;
pr.r = makeRect (0, 0, 0, 0);
if (str_mid (str, 0, 1) == "[") {
tmp = "(" + str_mid (str, 1, -1) + ")";
item = [PLItem fromString:tmp];
xp = stoi ([(PLString*) [(PLArray*) item getObjectAtIndex:0] string]);
yp = stoi ([(PLString*) [(PLArray*) item getObjectAtIndex:1] string]);
xl = stoi ([(PLString*) [(PLArray*) item getObjectAtIndex:2] string]);
yl = stoi ([(PLString*) [(PLArray*) item getObjectAtIndex:3] string]);
pr.r = makeRect (xp, yp, xl, yl);
}
return pr.p;
}
@static @param
string_from_plist (PLString *plstring)
{
local @param ret;
local string str = [plstring string];
ret = nil;
if (str_mid (str, 0, 1) == "[")
return rect_from_plist (plstring);
ret.string_val = nil;
return ret;
}
@param
object_from_plist (PLItem *plist)
{
local @param ret;
ret = nil;
switch ([plist type]) {
case QFDictionary:
return class_from_plist ((PLDictionary *) plist);
case QFArray:
return array_from_plist ((PLArray *) plist);
case QFBinary:
ret.pointer_val = nil;
return ret;
case QFString:
return string_from_plist ((PLString *) plist);
}
return nil;
}
PLItem *
read_plist (string fname)
{
local QFile file;
local PLItem *plist;
file = QFS_OpenFile (fname);
if (!file) {
dprint ("could not load menu.plist\n");
return nil;
}
plist = [PLItem fromFile:file];
Qclose (file);
return plist;
}