ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/lib/gprim/geom/geomstream.c

This is geomstream.c in view mode; [Download] [Up]

/* Copyright (c) 1992 The Geometry Center; University of Minnesota
   1300 South Second Street;  Minneapolis, MN  55454, USA;
   
This file is part of geomview/OOGL. geomview/OOGL is free software;
you can redistribute it and/or modify it only under the terms given in
the file COPYING, which you should have received along with this file.
This and other related software may be obtained via anonymous ftp from
geom.umn.edu; email: software@geom.umn.edu. */

/* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */

#include <stdio.h>
#include <string.h>
#include "geomclass.h"
#include "streampool.h"
#include "handleP.h"


HandleOps GeomOps = {
	"geom",
	GeomStreamIn,
	GeomStreamOut,
	GeomDelete,
	NULL,		/* resync */
	NULL,		/* close pool */
};

Geom *
GeomLoad(char *fname)
{
    FILE *inf = fopen(fname, "r");
    Geom *g;

    if(inf == NULL) {
	OOGLError(0, "GeomLoad: can't open %s: %s", fname, sperror());
	return NULL;
    }
    g = GeomFLoad(inf, fname);
    fclose(inf);
    return g;
}

Geom *
GeomFLoad(FILE *inf, char *fname)
{
    Pool *p;
    Geom *g = NULL;

    p = PoolStreamTemp(fname, inf, 0, NULL);
    GeomStreamIn(p, NULL, &g);
    PoolDelete(p);
    return g;
}

int
GeomFLoadEmbedded( Geom **gp, Handle **hp, FILE *inf, char *fname )
{
    Pool *p;
    int nope;

    p = PoolStreamTemp(fname, inf, 0, NULL);
    nope = GeomStreamIn(p, hp, gp);
    PoolDelete(p);
    return !nope;
}

Geom *
GeomSave(Geom *g, char *fname)
{
    Pool *p;
    int ok;

    p = PoolStreamTemp(fname, NULL, 1, &GeomOps);
    if(p == NULL) {
	OOGLError(0, "GeomSave: Can't open %s: %s", fname, sperror());
	return NULL;
    }
    PoolSetOType(p, PO_DATA);
    ok = GeomStreamOut(p, NULL, g);
    PoolClose(p);
    PoolDelete(p);
    return ok ? g : NULL;
}

Geom *
GeomFSave(Geom *g, FILE *outf, char *fname)
{
    Pool *p;
    int ok;

    p = PoolStreamTemp(fname, outf, 1, NULL);
    PoolSetOType(p, PO_DATA);
    PoolIncLevel(p,1);
    ok = GeomStreamOut(p, NULL, g);
    PoolDelete(p);
    return ok ? g : NULL;
}

Geom *
GeomFSaveEmbedded( Geom *g, Handle *handle, FILE *outf, char *fname )
{
    Pool *p;
    int ok;

    p = PoolStreamTemp(fname, outf, 1, NULL);
    PoolSetOType(p, PO_HANDLES);
    PoolIncLevel(p, 1);		/* Enforce level > 0 to get { braces } */
    ok = GeomStreamOut(p, handle, g);
    PoolDelete(p);
    return ok ? g : NULL;
}

int
GeomEmbedPrefix(int c)
{ return (c == '{' || c == '=' || c == '@' || c == '<'); }

int
GeomStreamIn(Pool *p, Handle **hp, Geom **gp)
{
    FILE *f;
    Handle *h = NULL;
    Handle *hname = NULL;
    Geom *g = NULL;
    Handle *aphandle = NULL;
    Appearance *ap = NULL;
    GeomClass *Class;
    void *it;
    struct stdio_mark *mark = NULL;
    int first;
    int empty = 1, braces = 0;
    Geom **tgp;
    Handle **thp;
    int c;
    char *w, *raww, *tail;
    int brack = 0;
    int more;
    char longname[512];

    if(p == NULL || (f = PoolInputFile(p)) == NULL)
	return 0;

    /* Skip a semicolon if it's the first thing we see -- 'stuff' compatibility.
     */
    if(fnextc(f, 0) == ';')
	fgetc(f);

    do {
	more = 0;
	switch(c = fnextc(f, 0)) {
	case '<':
	case ':':
	case '@':
	    fgetc(f);
	    w = fdelimtok("{}()", f, 0);
	    /*
	     * Consider doing a path search.
	     * Do this before calling HandleReferringTo()
	     * to prevent spurious error messages.
	     */
	    if(c == '<' && (h = HandleByName(w, &GeomOps)) == NULL && w[0] != '/') {
		w = findfile(PoolName(p), raww = w);
		if(w == NULL) {
		    OOGLSyntax(PoolInputFile(p),
			"Error reading \"%s\": can't find file \"%s\"",
			PoolName(p), raww);
		}
	    }
	    h = HandleReferringTo(c, w, &GeomOps, NULL);
	    if(h != NULL) {
		g = (Geom *)HandleObject(h);
		RefIncr((Ref*)g);
	    }
	    break;

	case '{':
	    brack++;
	    fgetc(f);
	    break;
	case '}':
	    if(brack--) { fgetc(f); braces = 1; }
	    break;

	case 'g':
	    if(fexpectstr(f, "geom"))
		return 0;
	    more = 1;
	    break;

	case 'd':
	    if(fexpectstr(f, "define"))
		return 0;
	    more = 1;
	    hname = HandleCreate( ftoken(PoolInputFile(p), 0), &GeomOps );
	    break;

	case 'a':
	    if(fexpectstr(f, "appearance"))
		return 0;
	    ap = ApFLoad(NULL, PoolInputFile(p), PoolName(p));
	    more = 1;
	    break;

	case '=':
	    fgetc(f);			/* Skip '=' and fall into... */

	default:
	    /*
	     * Load literal object.
	     * First try to guess object type from its file name.
	     */
	    empty = 0;
	    (void) fnextc(f, 0);	/* [Prime stdio buffer] */
	    mark = stdio_setmark( NULL, PoolInputFile(p) );

	    Class = GeomFName2Class( PoolName(p) );

	    g = NULL;
	    first = 1;
	    tgp = gp ? gp : &g;
	    thp = hp ? hp : &h;

	    if(Class) {
		if(Class->import)
		    g = (*Class->import)(p);
		else if(Class->fload)
		    g = (*Class->fload)(PoolInputFile(p), PoolName(p));
		first = 0;
		if(g)
		    break;
	    }

	    /*
	     * If not, try all known classes.
	     */
	    GeomKnownClassInit();	/* Ensure all classes entered */

	    it = GeomClassIterate();
	    while (g == NULL && (Class = GeomNextClass(&it)) != NULL) {
		if(Class->import == NULL && Class->fload == NULL)
		    continue;
		/*
		 * Try to seek back to our initial position.
		 */
		if(!first && !stdio_seekmark(mark)) {
		    /* No luck.  Might as well give up right now. */
		    OOGLSyntax(PoolInputFile(p),
			"Error reading \"%s\": can't seek back far enough (on pipe?)",
				PoolName(p));
			break;
		}

		if(Class->import)
		    g = (*Class->import)(p);
		else if(Class->fload)
		    g = (*Class->fload)(PoolInputFile(p), PoolName(p));
		first = 0;
	    }
	    if(g == NULL) {
		OOGLFree(mark);
		return 0;
	    }
	}
    } while(brack > 0 || more);


    if(hname != NULL) {
	if(g)
	    HandleSetObject(hname, (Ref *)g);
	h = hname;
    }

    /*
     * Leave results where we're told to
     */
    if(h != NULL && hp != NULL && *hp != h) {
	if(*hp)
	    HandlePDelete(hp);
	*hp = h;
    }
    if(ap != NULL || aphandle != NULL) {
	if(g == NULL)
	   g = GeomCreate("inst", CR_END);
	if(g->ap)
	    ApDelete(g->ap);
	if(g->aphandle)
	    HandlePDelete(&g->aphandle);
	g->ap = ap;
	g->aphandle = aphandle;
    }
    if(g != NULL && gp != NULL && *gp != g) {
	if(*gp != NULL)
	    GeomDelete(*gp);
	*gp = g;
    } else if(g)		/* Maintain ref count */
	GeomDelete(g);

    if(mark != NULL)
	OOGLFree(mark);
    return (g != NULL || h != NULL || (empty && braces));
}


int
GeomStreamOut(Pool *p, Handle *h, Geom *g)
{
    int putdata;
    int brack;

    if(PoolOutputFile(p) == NULL)
	  return 0;

    if(g == NULL && h != NULL && h->object != NULL)
	g = (Geom *)h->object;

    if(g == NULL && h == NULL) {
	fprintf(PoolOutputFile(p), "{ }\n");
	return 1;
    }

    brack = (p->level > 0 || (g && (g->ap || g->aphandle)) || h != NULL);

    if(brack)
	fprintf(PoolOutputFile(p), "{ ");

    if(p->otype & 4) fprintf(PoolOutputFile(p), "# %d refs\n", g->ref_count); /* debug */

    if(g && (g->ap || g->aphandle))
	ApFSave(g->ap, g->aphandle, PoolOutputFile(p), PoolName(p));

    putdata = PoolStreamOutHandle( p, h, g != NULL );
    if(g != NULL && putdata) {
	if(brack)
	    fprintf(PoolOutputFile(p), "= ");
	PoolIncLevel(p, 1);
	if(g->Class->export)
	    (*g->Class->export)(g, p);
	else if(g->Class->fsave)
	    (*g->Class->fsave)(g, PoolOutputFile(p), PoolName(p));
	PoolIncLevel(p, -1);
    }
    if(brack)
	fprintf(PoolOutputFile(p), "}\n");
    return !ferror(PoolOutputFile(p));
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.