#include "fido.h"
#include <ascii.h>
#include "fidomem.h"
#include "proto.h"

/* List zones, nets and nodes from the node list. 

	n == 0		list all
	n == 1		list nodes
	n == 2		list nets
	n == 3		list zones

	The passed node structure contains the desired zone or net for
n == 1 and 2.
*/

int list_nodes(d,n)
struct _node *d;
int n;
{
struct _idx *ip,buff[50];
struct _node target,inode;
int f,ii,ic;
unsigned recd;			/* recd # we find */
FLAG found;			/* yes we found one */
long o;				/* index file starting offset */

	if (node_files()) {
		mprintf(CM+139);				/* no nodelist */
		return(0);
	}
	cpy_node(&target,d);				/* make a clean copy */
	fix_node(&target);				/* make it presentable */

	switch (n) {

/* List ZONEs and NETs; in the NDX file, start from BOF. */

		case 3:					/* ZONEs */
		case 2:					/* NETs */
			f= ndxfile; o= 0L; break;

/* List NODEs: in the IDX file, start from the NET HOST. 'recd' is the record
number we start with. */

		case 1:					/* NODEs */
			target.number= 0;		/* set host node */
			recd= index_node(&target);	/* locate the host */
			if (recd == -1) return(0);	/* (not found) */
			o= recd; o *= sizeof(struct _idx); /* starting position */
			f= idxfile; 			/* main index file */
			break;

/* List all NODEs. 'recd' is the starting record number (zero). */

		case 0:					/* all nodes */
			recd= 0; f= idxfile; break;

		default: return(0);			/* oops */
	}
	lseek(f,o,0);					/* where to start */
	ii= ic= found= 0;

/* Now read index entries from the index file, and list them as
instructed. */

	while (1) {					/* now do the work */
		if (abort) return(found);		/* manual abort */

		if (ii >= ic) {				/* read some, */
			ii= 0;
			ic= (read(f,buff,sizeof(buff)) / sizeof(struct _idx));
			if (! ic) break;		/* end of file */
			ip= buff;			/* our work pointer */
		}

/* Note that the thing in theindex file is not a real _node; we fake it. */

		cpy_node(&inode,(struct _node *)&ip);	/* copy (fake) node */
		inode.point= 0;				/* repair it */
		fix_node(&inode);			/* make it presentable */

		switch (n) {

/* ZONEs: List all zone hosts. */

			case 3:				/* list ZONEs */
				if (! is_zonehost(&inode)) break;
				recd= ip-> pos;		/* set recd number */
				goto listit;

/* NETs: List only hosts in the specified zone. Once we find a net, list them
until we enter another zone, then stop. */

			case 2:				/* list NETs */
				if (! same_zone(&target,&inode)) {
					if (found) return(found);
					else break;
				}
				if (! is_host(&inode)) break;
				recd= ip-> pos;		/* pos is recd */
				goto listit;

/* List NODEs: Since we started by seeking to the net host, list nodes
until we enter another net. */

			case 1:				/* nodes this net */
				if (! same_net(&target,&inode))
					return(found);	/* stop if different net */

/* List all nodes; just display. */

			case 0:
listit:;			found= 1;
				get_ndat(recd);		/* 'recd' maintained */
				listnode(&ndat);
				break;
		}
		++ip; ++ii;				/* next struct, next record */
		++recd;					/* (valid for 0 and 1) */
	}
	return(found);
}

/* List node information. */

char *bucks_str();

void listnode(nd)
struct _ndat *nd;
{
char *cp,*b;
int n;
	
	b= "";					/* default: dont display cost */
	if (is_zonehost(&nd-> node)) {
		cp= "ZONE   ";
		n= nd-> node.zone;

	} else if (is_host(&nd-> node)) {
		cp= "NET    ";
		n= nd-> node.net;

	} else {				/* a node */
		cp= "       ";
		n= nd-> node.number;		/* for Nodes */
		b= bucks_str(nd-> cost);	/* display cost */
	}

	mprintf(0,"%s%5u %s, %s %s\r\n",cp,n,nd-> name,nd-> city,b);
}
