/*
 * dump-fig.c --
 *
 *      Operations to dump graphic representation of MIBs in fig format.
 *
 * Copyright (c) 1999 J. Schoenwaelder, Technical University of Braunschweig.
 *
 * See the file "COPYING" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * @(#) $Id: dump-fig.c 8676 2008-01-17 23:11:17Z ispringer $
 */

#include <config.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "smi.h"
#include "smidump.h"


#define	 X_OFFSET	225
#define	 Y_OFFSET	225
#define	 X_INDENT	225
#define	 Y_INDENT	225



static void setupPage()
{
    printf("#FIG 3.2\n"
	   "#\n"
	   "# This FIG file has been generated by smidump " SMI_VERSION_STRING
	   ". Do not edit.\n#\n"
	   "Landscape\n"
	   "Center\n"
	   "Metric\n"
	   "A4\n"
	   "50.00\n"
	   "Single\n"
	   "-1\n"
	   "1200 2\n");
}



static void printString(int x, int y, int angle, char *string)
{
    int height = 180, length = 22;

    printf("4 0 0 0 0 18 12 0.0 4 %d %d %d %d %s\\001\n",
	   height, length, x, y, string);
}



static int isGroup(SmiNode *smiNode)
{
    SmiNode *childNode;
    
    for(childNode = smiGetFirstChildNode(smiNode);
	childNode;
	childNode = smiGetNextChildNode(childNode)) {
	if ((childNode->nodekind == SMI_NODEKIND_SCALAR
	     || childNode->nodekind == SMI_NODEKIND_TABLE)
	    && childNode->status == SMI_STATUS_CURRENT) {
	    return 1;
	}
    }

    return 0;
}



static void printGroup(int *x, int *y, SmiNode *smiNode)
{
    SmiNode *childNode;
    char string[4096];

    *y += Y_OFFSET;
    printString(*x, *y, 0, smiNode->name);

    for(childNode = smiGetFirstChildNode(smiNode);
	childNode;
	childNode = smiGetNextChildNode(childNode)) {
	if (childNode->nodekind == SMI_NODEKIND_SCALAR
	    || childNode->nodekind == SMI_NODEKIND_COLUMN) {
	    if (childNode->status != SMI_STATUS_OBSOLETE) {
		*y += Y_OFFSET;
		sprintf(string, "%s(%d)", childNode->name,
			childNode->oid[childNode->oidlen-1]);
		printString(*x + X_INDENT, *y, 0, string);
	    }
	}
    }
    *y += Y_OFFSET;
}



static void printGroups(int *x, int *y, SmiModule *smiModule)
{
    SmiNode *smiNode;

    for(smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
	smiNode;
	smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
	if (isGroup(smiNode)) {
	    printGroup(x, y, smiNode);
	}
	if (smiNode->nodekind == SMI_NODEKIND_ROW) {
	    printGroup(x, y, smiNode);
	}
    }
}



void dumpFigTree(Module *module)
{
    SmiModule    *smiModule;
    int		 x, y;

    smiModule = module->smiModule;

    setupPage();

    x = X_OFFSET, y = Y_OFFSET;
    printGroups(&x, &y, smiModule);
}



static void printClass(int *x, int *y, SmiNode *smiNode)
{
    SmiNode *childNode;
    SmiType *smiType;
    char string[4096];

    *y += Y_OFFSET;
    printString(*x, *y, 0, smiNode->name);

    for(childNode = smiGetFirstChildNode(smiNode);
	childNode;
	childNode = smiGetNextChildNode(childNode)) {
	if (childNode->nodekind == SMI_NODEKIND_SCALAR
	    || childNode->nodekind == SMI_NODEKIND_COLUMN) {
	    if (childNode->status != SMI_STATUS_OBSOLETE) {
		smiType = smiGetNodeType(childNode);
		*y += Y_OFFSET;
		sprintf(string, "%s : %s", childNode->name, smiType->name);
		printString(*x + X_INDENT, *y, 0, string);
	    }
	}
    }
    *y += Y_OFFSET;
}



static void printClasses(int *x, int *y, SmiModule *smiModule)
{
    SmiNode *smiNode;

    for(smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
	smiNode;
	smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
	if (isGroup(smiNode)) {
	    printClass(x, y, smiNode);
	}
	if (smiNode->nodekind == SMI_NODEKIND_ROW) {
	    printClass(x, y, smiNode);
	}
    }
}



void dumpFigUml(Module *module)
{
    SmiModule    *smiModule;
    int		 x, y;

    smiModule = module->smiModule;

    setupPage();

    x = X_OFFSET, y = Y_OFFSET;
    printClasses(&x, &y, smiModule);
}



void init_fig()
{
    static SmidumpDriver driverTree = {
	"fig-tree",
	dumpFigTree,
	SMI_FLAG_NODESCR,
	SMIDUMP_DRIVER_CANT_UNITE | SMIDUMP_DRIVER_CANT_OUTPUT,
	"tree graphics in xfig fig format",
	NULL,
	NULL
    };
    static SmidumpDriver driverUml = {
	"fig-uml",
	dumpFigUml,
	SMI_FLAG_NODESCR,
	SMIDUMP_DRIVER_CANT_UNITE | SMIDUMP_DRIVER_CANT_OUTPUT,
	"UML graphics in xfig fig format",
	NULL,
	NULL
    };
    
    smidumpRegisterDriver(&driverTree);
    smidumpRegisterDriver(&driverUml);
}
