Use QF's property lists for the project file.

This commit is contained in:
Bill Currie 2010-10-04 19:43:33 +09:00
parent 1a994ab784
commit 05a8b981a5
6 changed files with 150 additions and 460 deletions

View file

@ -5,40 +5,25 @@
#include "Storage.h"
typedef struct {
char *key;
char *value;
} dict_t;
struct script_s;
@interface Dict: Storage
@interface Dict: NSObject
{
struct plitem_s *plist;
}
- (id) initFromFile: (FILE *)fp;
- (id) parseMultipleFrom: (const char *)value;
- (int) getValueUnits: (const char *)key;
- (id) delString: (const char *)string fromValue: (const char *)key;
- (id) addString: (const char *)string toValue: (const char *)key;
- (char *) convertListToString: (id)list;
- (struct plitem_s *) getArrayFor: (const char *)name;
- (const char *) getStringFor: (const char *)name;
- (id) removeKeyword: (const char *)key;
- (unsigned int) getValueFor: (const char *)name;
- (id) changeStringFor: (const char *)key to: (const char *)value;
- (dict_t *) findKeyword: (const char *)key;
- (id) writeBlockTo: (FILE *)fp;
- (id) writeFile: (const char *)path;
// INTERNAL
- (id) init;
- (id) parseBraceBlock: (struct script_s *)script;
@end
int GetNextChar (FILE * fp);

View file

@ -1,18 +1,14 @@
#include "QF/dstring.h"
#include "QF/qfplist.h"
#include "QF/script.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "Dict.h"
@implementation Dict
- (id) init
{
[super initCount: 0 elementSize: sizeof (dict_t)
description: NULL];
return self;
}
/*
- (id) print
{
NSUInteger i;
@ -24,7 +20,7 @@
}
return self;
}
*/
/*
===========
copyFromZone
@ -34,24 +30,8 @@ JDC
*/
- (id) copy
{
id new;
NSUInteger i;
dict_t *d;
char *old;
new = [super copy];
for (i = 0; i < numElements; i++) {
d = [self elementAt: i];
old = d->key;
d->key = malloc (strlen (old) + 1);
strcpy (d->key, old);
old = d->value;
d->value = malloc (strlen (old) + 1);
strcpy (d->value, old);
}
return new;
Sys_Printf ("Dict copy: not implemented\n");
return 0;
}
- (id) initFromFile: (FILE *)fp
@ -60,7 +40,6 @@ JDC
char *str;
size_t read;
const size_t readsize = 1024;
script_t *script;
[self init];
@ -71,14 +50,21 @@ JDC
str[read] = 0;
} while (read == readsize);
script = Script_New ();
Script_Start (script, "project file", text->str);
self = [self parseBraceBlock: script];
Script_Delete (script);
plist = PL_GetPropertyList (text->str);
dstring_delete (text);
if (!plist)
return 0;
return self;
}
- (void) dealloc
{
if (plist)
PL_Free (plist);
[super dealloc];
}
// ===============================================
//
// Dictionary pair functions
@ -90,17 +76,11 @@ JDC
//
- (id) writeBlockTo: (FILE *)fp
{
int max;
int i;
dict_t *d;
char *data;
fprintf (fp, "{\n");
max = [super count];
for (i = 0; i < max; i++) {
d = [super elementAt: i];
fprintf (fp, "\t{\"%s\"\t\"%s\"}\n", d->key, d->value);
}
fprintf (fp, "}\n");
data = PL_WritePropertyList (plist);
fputs (data, fp);
free (data);
return self;
}
@ -132,60 +112,36 @@ JDC
//
// ===============================================
//
// Find a keyword in storage
// Returns * to dict_t, otherwise NULL
//
- (dict_t *) findKeyword: (const char *)key
{
int max;
int i;
dict_t *d;
max = [super count];
for (i = 0; i < max; i++) {
d = [super elementAt: i];
if (!strcmp (d->key, key))
return d;
}
return NULL;
}
//
// Change a keyword's string
//
- (id) changeStringFor: (const char *)key to: (const char *)value
{
dict_t *d;
dict_t newd;
d = [self findKeyword: key];
if (d != NULL) {
free (d->value);
d->value = malloc (strlen (value) + 1);
strcpy (d->value, value);
} else {
newd.key = malloc (strlen (key) + 1);
strcpy (newd.key, key);
newd.value = malloc (strlen (value) + 1);
strcpy (newd.value, value);
[self addElement: &newd];
}
PL_D_AddObject (plist, key, PL_NewString (value));
return self;
}
- (plitem_t *) getArrayFor: (const char *)name
{
plitem_t *item;
item = PL_ObjectForKey (plist, name);
if (item && PL_Type (item) == QFArray)
return item;
return 0;
}
//
// Search for keyword, return the string *
//
- (const char *) getStringFor: (const char *)name
{
dict_t *d;
plitem_t *item;
const char *str;
d = [self findKeyword: name];
if (d != NULL)
return d->value;
return (char *) "";
item = PL_ObjectForKey (plist, name);
if (item && (str = PL_String (item)))
return str;
return "";
}
//
@ -193,12 +149,7 @@ JDC
//
- (unsigned int) getValueFor: (const char *)name
{
dict_t *d;
d = [self findKeyword: name];
if (d != NULL)
return atol (d->value);
return 0;
return atol ([self getStringFor: name]);
}
//
@ -206,330 +157,13 @@ JDC
//
- (int) getValueUnits: (const char *)key
{
id temp;
int count;
plitem_t *item;
temp = [self parseMultipleFrom: key];
count = [temp count];
[temp release];
item = PL_ObjectForKey (plist, key);
if (!item || PL_Type (item) != QFArray)
return 0;
return count;
}
//
// Convert List to string
//
- (char *) convertListToString: (id)list
{
int i;
int max;
dstring_t *tempstr;
char *s;
max = [list count];
tempstr = dstring_newstr ();
for (i = 0; i < max; i++) {
s = [list elementAt: i];
dstring_appendstr (tempstr, s);
dstring_appendstr (tempstr, " ");
}
return dstring_freeze (tempstr);
}
//
// JDC: I wrote this to simplify removing vectors
//
- (id) removeKeyword: (const char *)key
{
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return self;
[self removeElementAt: d - (dict_t *) dataPtr];
return self;
}
//
// Delete string from keyword's value
//
- (id) delString: (const char *)string fromValue: (const char *)key
{
id temp;
int count;
int i;
char *s;
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return NULL;
temp = [self parseMultipleFrom: key];
count = [temp count];
for (i = 0; i < count; i++) {
s = [temp elementAt: i];
if (!strcmp (s, string)) {
[temp removeElementAt: i];
free (d->value);
d->value = [self convertListToString: temp];
[temp release];
break;
}
}
return self;
}
//
// Add string to keyword's value
//
- (id) addString: (const char *)string toValue: (const char *)key
{
char *newstr;
dict_t *d;
d = [self findKeyword: key];
if (d == NULL)
return NULL;
newstr = nva ("%s\t%s", d->value, string);
free (d->value);
d->value = newstr;
return self;
}
// ===============================================
//
// Use these for multiple parameters in a keyword value
//
// ===============================================
const char *searchStr;
char item[4096];
- (id) setupMultiple: (const char *)value
{
searchStr = value;
return self;
}
- (char *) getNextParameter
{
char *s;
if (!searchStr)
return NULL;
strcpy (item, searchStr);
s = FindWhitespcInBuffer (item);
if (!*s) {
searchStr = NULL;
} else {
*s = 0;
searchStr = FindNonwhitespcInBuffer (s + 1);
}
return item;
}
//
// Parses a keyvalue string & returns a Storage full of those items
//
- (id) parseMultipleFrom: (const char *)key
{
#define ITEMSIZE 128
id stuff;
char string[ITEMSIZE];
const char *s;
s = [self getStringFor: key];
if (s == NULL)
return NULL;
stuff = [[Storage alloc]
initCount: 0 elementSize: ITEMSIZE description: NULL];
[self setupMultiple: s];
while ((s = [self getNextParameter])) {
bzero (string, ITEMSIZE);
strcpy (string, s);
[stuff addElement: string];
}
return stuff;
}
// ===============================================
//
// Dictionary pair parsing
//
// ===============================================
//
// parse all keyword/value pairs within { } 's
//
- (id) parseBraceBlock: (script_t *)script
{
dict_t pair;
if (!Script_GetToken (script, YES))
return NULL;
if (strcmp (Script_Token (script), "{"))
return NULL;
do {
if (!Script_GetToken (script, YES))
return NULL;
if (!strcmp (Script_Token (script), "}"))
break;
if (strcmp (Script_Token (script), "{"))
return NULL;
if (!Script_GetToken (script, YES))
return NULL;
pair.key = strdup (Script_Token (script));
if (!Script_GetToken (script, YES))
return NULL;
pair.value = strdup (Script_Token (script));
if (!Script_GetToken (script, YES))
return NULL;
if (strcmp (Script_Token (script), "}"))
return NULL;
[super addElement: &pair];
} while (1);
return self;
return PL_A_NumObjects (item);
}
@end
// ===============================================
//
// C routines for string parsing
//
// ===============================================
int
GetNextChar (FILE * fp)
{
int c;
int c2;
c = getc (fp);
if (c == EOF)
return -1;
if (c == '/') { // parse comments
c2 = getc (fp);
if (c2 == '/') {
while ((c2 = getc (fp)) != '\n')
;
c = getc (fp);
} else {
ungetc (c2, fp);
}
}
return c;
}
void
CopyUntilWhitespc (FILE * fp, char *buffer)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return;
if (c <= ' ') {
*buffer = 0;
return;
}
*buffer++ = c;
}
}
void
CopyUntilQuote (FILE * fp, char *buffer)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return;
if (c == '\"') {
*buffer = 0;
return;
}
*buffer++ = c;
}
}
int
FindBrace (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c == '{' || c == '}')
return c;
}
return -1;
}
int
FindQuote (FILE * fp)
{
int count = 800;
int c;
while (count--) {
c = GetNextChar (fp);
if (c == EOF)
return -1;
if (c == '\"')
return c;
}
return -1;
}
char *
FindWhitespcInBuffer (char *buffer)
{
int count = 1000;
char *b = buffer;
while (count--) {
if (*b <= ' ')
return b;
else
b++;
}
return NULL;
}
char *
FindNonwhitespcInBuffer (char *buffer)
{
int count = 1000;
char *b = buffer;
while (count--) {
if (*b > ' ')
return b;
else
b++;
}
return NULL;
}

View file

@ -49,7 +49,7 @@ QuakeEd_LANGUAGES= \
# Header files
#
QuakeEd_HEADERS= \
CameraView.h Clipper.h Dict.h DictList.h Entity.h EntityClass.h \
CameraView.h Clipper.h Dict.h Entity.h EntityClass.h \
InspectorControl.h KeypairView.h Map.h PopScrollView.h Preferences.h \
Project.h QuakeEd.h SetBrush.h Storage.h TexturePalette.h TextureView.h \
Things.h XYView.h ZScrollView.h ZView.h render.h \
@ -60,7 +60,7 @@ QuakeEd_HEADERS= \
# Class files
#
QuakeEd_OBJC_FILES= \
CameraView.m Clipper.m Dict.m DictList.m Entity.m EntityClass.m \
CameraView.m Clipper.m Dict.m Entity.m EntityClass.m \
InspectorControl.m KeypairView.m Map.m PopScrollView.m Preferences.m \
Project.m QuakeEd.m QuakeEd_main.m SetBrush.m Storage.m TexturePalette.m \
TextureView.m Things.m XYView.m ZScrollView.m ZView.m render.m

View file

@ -28,9 +28,9 @@ extern id project_i;
id basepathinfo_i; // outlet to base path info textfield
id mapbrowse_i; // outlet to QuakeEd Maps browser
id currentmap_i; // outlet to current map textfield
id mapList; // list of map names (Storage)
id descList; // list of map descriptions (Storage)
id wadList; // list of wad names (Storage)
struct plitem_s *mapList; // list of map names (Storage)
struct plitem_s *descList; // list of map descriptions (Storage)
struct plitem_s *wadList; // list of wad names (Storage)
id pis_panel_i; // outlet to Project Info Settings (PIS)
// panel

View file

@ -6,6 +6,7 @@
#include <unistd.h>
#include "QF/qfplist.h"
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/va.h"
@ -104,12 +105,11 @@ id project_i;
changeString ('@', '\"', string_entities);
}
// Build list of wads
wadList = [projectInfo parseMultipleFrom: WADSKEY];
wadList = [projectInfo getArrayFor: WADSKEY];
// Build list of maps & descriptions
mapList = [projectInfo parseMultipleFrom: MAPNAMESKEY];
descList = [projectInfo parseMultipleFrom: DESCKEY];
[self changeChar: '_' to: ' ' in: descList];
mapList = [projectInfo getArrayFor: MAPNAMESKEY];
descList = [projectInfo getArrayFor: DESCKEY];
[self initProjSettings];
@ -204,23 +204,24 @@ id project_i;
//
- (void) browser: sender createRowsForColumn: (int)column inMatrix: matrix
{
id cell, list;
int max;
char *name;
int i;
id cell;
plitem_t *list;
int max;
const char *name;
int i;
if (sender == mapbrowse_i) {
list = mapList;
} else if (sender == pis_wads_i) {
list = wadList;
} else {
list = nil;
list = 0;
Sys_Error ("Project: unknown browser to fill");
}
max = [list count];
max = list ? PL_A_NumObjects (list) : 0;
for (i = 0; i < max; i++) {
name = [list elementAt: i];
name = PL_String (PL_ObjectAtIndex (list, i));
[matrix addRow];
cell = [matrix cellAtRow: i column: 0];
[cell setStringValue: [NSString stringWithCString: name]];
@ -243,7 +244,7 @@ id project_i;
matrix = [sender matrixInColumn: 0];
row = [matrix selectedRow];
fname = va ("%s/%s.map", path_mapdirectory,
(const char *) [mapList elementAt: row]); // XXX Storage
PL_String (PL_ObjectAtIndex (mapList, row)));
panel = NSGetAlertPanel (@"Loading...",
@"Loading map. Please wait.", NULL, NULL, NULL);
@ -267,9 +268,9 @@ id project_i;
Sys_Printf ("loading %s\n", wf);
// set the row in the settings inspector wad browser
c = [wadList count];
c = PL_A_NumObjects (wadList);
for (i = 0; i < c; i++) {
name = (const char *) [wadList elementAt: i]; // XXX Storage
name = PL_String (PL_ObjectAtIndex (wadList, i));
if (!strcmp (name, wf)) {
[[pis_wads_i matrixInColumn: 0] selectCellAtRow: i column: 0];
break;
@ -291,14 +292,14 @@ id project_i;
//
- (id) clickedOnWad: sender
{
id matrix;
int row;
char *name;
id matrix;
int row;
const char *name;
matrix = [sender matrixInColumn: 0];
row = [matrix selectedRow];
name = (char *) [wadList elementAt: row]; // XXX Storage
name = PL_String (PL_ObjectAtIndex (wadList, row));
[self setTextureWad: name];
return self;

View file

@ -1,13 +1,83 @@
{
{"basepath" "/raid/quake/id1"}
{"maps" "jrbase1 jrbase2 jrbase4 jrwiz1 jrwiz2 jrdungn jrmed1 jrmed2 jrstart tim4 tim5 tim6 tim7 tim9 tboss amtest98 ammap2 amtest1 amdm3 amdem1 ammet2 amlev13 ammech3 schurch smotte sramp2 scath sally spit stemple"}
{"desc" "jrbase1 jrbase2 jrbase4 jrwiz1 jrwiz2 jrdungn jrmed1 jrmed2 jrstart tim4 tim5 tim6 tim7 tim9 tboss amtest98 ammap2 amtest1 amdm3 amdem1 ammet2 amlev13 ammech3 schurch smotte sramp2 scath sally spit stemple"}
{"wads" "gfx/medieval.wad gfx/base.wad gfx/wizard.wad gfx/metal.wad gfx/tim.wad gfx/items.wad gfx/start.wad"}
"basepath" = "/raid/quake/id1";
"maps" = (
"jrbase1",
"jrbase2",
"jrbase4",
"jrwiz1",
"jrwiz2",
"jrdungn",
"jrmed1",
"jrmed2",
"jrstart",
"tim4",
"tim5",
"tim6",
"tim7",
"tim9",
"tboss",
"amtest98",
"ammap2",
"amtest1",
"amdm3",
"amdem1",
"ammet2",
"amlev13",
"ammech3",
"schurch",
"smotte",
"sramp2",
"scath",
"sally",
"spit",
"stemple"
);
"desc" = (
"jrbase1",
"jrbase2",
"jrbase4",
"jrwiz1",
"jrwiz2",
"jrdungn",
"jrmed1",
"jrmed2",
"jrstart",
"tim4",
"tim5",
"tim6",
"tim7",
"tim9",
"tboss",
"amtest98",
"ammap2",
"amtest1",
"amdm3",
"amdem1",
"ammet2",
"amlev13",
"ammech3",
"schurch",
"smotte",
"sramp2",
"scath",
"sally",
"spit",
"stemple"
);
"wads" = (
"gfx/medieval.wad",
"gfx/base.wad",
"gfx/wizard.wad",
"gfx/metal.wad",
"gfx/tim.wad",
"gfx/items.wad",
"gfx/start.wad"
);
{"bspfullvis" "rsh satan @/LocalApps/qbsp $1 $2 ; /LocalApps/light -extra $2 ; /LocalApps/vis $2@"}
{"bspfastvis" "rsh satan @/LocalApps/qbsp $1 $2 ; /LocalApps/light $2 ; /LocalApps/vis -fast $2@"}
{"bspnovis" "rsh satan @/LocalApps/qbsp $1 $2 ; /LocalApps/light $2@"}
{"bsprelight" "rsh satan @/LocalApps/qbsp -onlyents $1 $2 ; /LocalApps/light -extra $2@"}
{"bspleaktest" "rsh satan @/LocalApps/qbsp -mark -notjunc $1 $2 ; /LocalApps/light $2@"}
{"bspentities" "rsh satan @/LocalApps/qbsp -onlyents $1 $2@"}
"bspfullvis" = "rsh satan \"/LocalApps/qbsp $1 $2 ; /LocalApps/light -extra $2 ; /LocalApps/vis $2\"";
"bspfastvis" = "rsh satan \"/LocalApps/qbsp $1 $2 ; /LocalApps/light $2 ; /LocalApps/vis -fast $2\"";
"bspnovis" = "rsh satan \"/LocalApps/qbsp $1 $2 ; /LocalApps/light $2\"";
"bsprelight" = "rsh satan \"/LocalApps/qbsp -onlyents $1 $2 ; /LocalApps/light -extra $2\"";
"bspleaktest" = "rsh satan \"/LocalApps/qbsp -mark -notjunc $1 $2 ; /LocalApps/light $2\"";
"bspentities" = "rsh satan \"/LocalApps/qbsp -onlyents $1 $2\"";
}