/*****************************************************************************
* Project:  Workstation inventory
* File:		DATAFILE.C
* Author:	Morgan B. Adair
* Date:		12/15/91
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nit.h>
#include "datafile.h"
#include "btrieve.h"
#include "recdecl.h"

#define MOUSE_DRVR_MAJOR_VER	0xFF00
#define MOUSE_DRVR_MINOR_VER	0x00FF

void DisplayType(int displayCode);
void OutputData(WS_INVENTORY_RECORD *entry);

char positionBlock[128];									/* Btrieve file position block */

void LoadBtrieve(void)
{
	system("btrieve");
}

int UnloadBtrieve(void)
{
	return(BTRV(BT_STOP, NULL, NULL, NULL, NULL, 0));
}

int BtrieveIsLoaded(void)
{
	int	status;
	char	dataBuffer[5];
	int	dataLength = 5;

	status = BTRV(BT_VERSION, NULL, dataBuffer, &dataLength, NULL, 0);
	if (status == BT_SUCCESS)
		return(TRUE);
	else
		return(FALSE);
}

int DataFileExists(char *filePath)
{
	FILE	*dataFile;

	/* assume that if file is there, it's the right file */
	dataFile = fopen(filePath, "r");
	if (dataFile) {
		fclose(dataFile);
		return(TRUE);
	} else
		return(FALSE);
}

int OpenDataFile(char *fileName)
{
	unsigned		bufferLength;
	WS_INVENTORY_RECORD	entry;
	int 			status;

	/* Figure out how long the record is */
	bufferLength = sizeof(WS_INVENTORY_RECORD);

	/* Call BTRIEVE Open operation */
	status = BTRV(BT_OPEN, positionBlock, (char *)&entry, (int *)&bufferLength, fileName, 1);

	/* Return the result */
	return(status);
}

int CreateDataFile(char *filePath)
{
	unsigned 	bufferLength;
	FILE_SPEC	fileBuffer;
	int 		status;

	/* Create a new Btrieve file for the program file data */
	/* Initialize buffer */
	memset(&fileBuffer, 0, sizeof(fileBuffer));

	/* Define the global file paramaters */
	fileBuffer.recordLength = sizeof(WS_INVENTORY_RECORD);
	fileBuffer.pageSize     = 1024;				/* use Btrieve's default page size */
	fileBuffer.fileFlags    = 0;
	fileBuffer.indexCount   = NUMBER_OF_KEYS;
	fileBuffer.preAlloc     = 0;

	/* Key 0: network/node (1 key, 2 segments) */
	/* Segment 1:  network address, binary key */
	fileBuffer.keyBuf[0].keyPos  = 1;
	fileBuffer.keyBuf[0].keyLen  = 4;
	/* BT_KEY_SEG means another segment of this key follows */
	fileBuffer.keyBuf[0].keyFlag = BT_KEY_EXT_TYPE | BT_KEY_SEG;
	fileBuffer.keyBuf[0].keyType = BT_KEY_BIN;

	/* Segment 2:  node address, binary key */
	fileBuffer.keyBuf[1].keyPos  = 5;
	fileBuffer.keyBuf[1].keyLen  = 6;
	/* last segment in this key, so no BT_KEY_SEG on the flags */
	fileBuffer.keyBuf[1].keyFlag = BT_KEY_EXT_TYPE;
	fileBuffer.keyBuf[1].keyType = BT_KEY_BIN;

	/* Figure out the data buffer length */
	bufferLength = sizeof(fileBuffer);

	/*--- Call Btrieve with a Create request. ---*/
	status = BTRV(BT_CREATE, positionBlock, (char *)&fileBuffer, (int *)&bufferLength, filePath, 0);

	return(status);
}

int ListItems(void)
{
	int			status;
	unsigned		dataLength;
	char			keyBuffer[80];
	WS_INVENTORY_RECORD	entry;

	/* Figure out the data buffer length */
	dataLength = sizeof(WS_INVENTORY_RECORD);

	/* Get the first item in the database */
	status = BTRV(BT_GET_FIRST, positionBlock, (char *)&entry, (int *)&dataLength, keyBuffer, 0);

	/* As long as there are more, keep printing them */
	while (status != BT_END_OF_FILE) {

		/* Die on errors other than ERR_END_OF_FILE */
		if (status != BT_SUCCESS)
			return(status);

		/* Show item to user */
		OutputData(&entry);

		/* Step forwards to the next item */
		status = BTRV(BT_GET_NEXT, positionBlock, (char *)&entry, (int *)&dataLength, keyBuffer, 0);
	}

	return(BT_SUCCESS);
}

void OutputData(WS_INVENTORY_RECORD *entry)
{
	int	i;

	printf("Network/node: ");
	for (i=0; i<4; i++)
		printf("%X", entry->network[i]);
	printf("/");
	for (i=0; i<6; i++)
		printf("%X", entry->node[i]);
	printf("\n");

	printf("\tUser name (on default server): %s\n", entry->userName);

	printf("\tIPX Version: %d.%02d\n", entry->IPXmajorVersion, entry->IPXminorVersion);
	printf("\tSPX Version: %d.%02d\n", entry->SPXmajorVersion, entry->SPXminorVersion);

	printf("\tShell Version: %d.%d, Rev %c\n", entry->shellMajorVersion,
						   entry->shellMinorVersion,
						   entry->shellRevisionLevel+'A');

	printf("\tMachine model: ");
	switch (entry->machineModel) {
		case	0x2D	:	printf("\tCompaq Portable\n");
					break;
		case	0x9A	:	printf("\tCompaq Portable Plus\n");
					break;
		case	0xF8	:	printf("\tIBM PS/2 Model 80\n");
					break;
		case	0xF9	:	printf("\tIBM PC Convertible\n");
					break;
		case	0xFA	:	printf("\tIBM PS/2 Model 30\n");
					break;
		case	0xFB	:	printf("\tIBM PC XT\n");
					break;
		case	0xFC	:	switch (entry->machineSubmodel) {
						case	0	:
						case	1	:	printf("\tIBM PC/AT\n");
									break;
						case	2	:	printf("\tIBM PC/XT286\n");
									break;
						case	4	:	printf("\tIBM PS/2 Model 50\n");
									break;
						case	5	:	printf("\tIBM PS/2 Model 60\n");
									break;
						case	0xB	:	printf("\tIBM PS/1\n");
									break;
						default		:	printf("\tIBM PC/AT or PS class\n");
									break;
					}
					break;
		case	0xFD	:	printf("\tIBM PCjr\n");
					break;
		case	0xFE	:	printf("\tIBM PC/XT, Portable PC, or Compaq DeskPro\n");
					break;
		case	0xFF	:	printf("\tIBM PC\n");
					break;
		default		:	printf("\tUnknown machine type %d\n", entry->machineModel);
					break;
	}

	switch (entry->processorType) {
		case 	0x0086	:	printf("\t8086 or 8088 processor\n");
					break;
		case 	0x0286	:	printf("\t80286 processor\n");
					break;
		case 	0x0386	:	printf("\t80386DX or 80386SX processor\n");
					break;
		case 	0x0486	:	printf("\t80486DX or 80486SX processor\n");
					break;
		default		:	printf("\tUnable to identify CPU\n");
					break;
	}

	printf("\tCoprocessor: ");
	switch (entry->coprocessorType) {
		case	0	:	printf("No coprocessor\n");
					break;
		case	0x0087	:	printf("8087 coprocessor\n");
					break;
		case	0x0287	:	printf("80287 coprocessor\n");
					break;
		case	0x0387	:	printf("80387 coprocessor\n");
					break;
		default		:	printf("Error getting coprocessor type: %u\n", entry->coprocessorType);
					break;
	}

	printf("\tBase memory: %dK\n", entry->conventionalMemoryK);

	printf("\tExtended memory: %dK\n", entry->extendedMemoryK);

	printf("\tExpanded memory: %dK\n", entry->expandedMemoryK);

	printf("\tVideo hardware:  ");
	DisplayType(entry->videoHardware);

	if (entry->alternateVideoHardware) {
		printf("\tAlternate display hardware:  ");
		DisplayType(entry->alternateVideoHardware);
	}

	printf("\tDOS version: %d.%02d\n", entry->DOSversionMajor, entry->DOSversionMinor);

	if (entry->NICtype)
		printf("\tNIC type: %s\n", entry->NICtype);
	else
		printf("\tNIC type: unable to identify\n");

	printf("\t%d floppy drives\n", entry->numFloppyDrives);

	printf("\t%d printers installed\n", entry->numPrintersInstalled);

	printf("\t%d serial ports\n", entry->numSerialPorts);

	if (entry->mouseDriverVersion)
		printf("\tMouse driver version: %d.%02d\n",
			(entry->mouseDriverVersion & MOUSE_DRVR_MAJOR_VER) >> 8,
			 entry->mouseDriverVersion & MOUSE_DRVR_MINOR_VER);

	if (!(entry->mouseType))
		printf("\tMouse type: no mouse found\n");
	else {
		printf("\tMouse type: ");
		switch (entry->mouseType) {
			case 1	:	printf("Bus mouse\n");
					break;
			case 2	:	printf("Serial mouse\n");
					break;
			case 3	:	printf("InPort mouse\n");
					break;
			case 4	:	printf("PS/2 mouse\n");
					break;
			case 5	:	printf("Hewlet-Packard mouse\n");
					break;
			default	:	printf("Unknown mouse type\n");
					break;
		}
	}

	for (i=0; i<entry->numFloppyDrives; i++) {
		printf("\tFloppy drive %d: ", i);
		switch (entry->floppyDriveType[i]) {
			case	1	:	printf("360KB\n");
						break;
			case	2	:	printf("1.2MB\n");
						break;
			case	3	:	printf("720KB\n");
						break;
			case	4	:	printf("1.44MB\n");
						break;
			default		:	printf("unable to identify type\n");
						break;
		}
	}

	for (i=0; i<entry->numHardDrives; i++)
		printf("\tHard drive %d: %ld bytes\n",
			i, entry->hardDriveSize[i]);
}


void DisplayType(int displayCode)
{
	switch	(displayCode) {
		case 0	:	printf("No display\n");
				break;
		case 1	:	printf("Monochrome with 5151 monitor\n");
				break;
		case 2	:	printf("CGA with 5153/4 monitor\n");
				break;
		case 4	:	printf("EGA with 5153/4 montior\n");
				break;
		case 5	:	printf("EGA with 5151 monitor\n");
				break;
		case 6	:	printf("PGS with 5175 monitor\n");
				break;
		case 7	:	printf("VGA with analog monochrome monitor\n");
				break;
		case 8	:	printf("VGA with analog color monitor\n");
				break;
		case 11	:	printf("Model 30 with analog monochrome monitor (MCGA)\n");
				break;
		case 12	:	printf("Model 30 with analog color monitor (MCGA)\n");
				break;
		default	:       printf("Unable to identify graphics hardware\n");
	}
}

int SearchItem(WS_INVENTORY_RECORD *entry)
{
	int		status;
	unsigned	dataLength;
	int		i;
	char		keyBuffer[KEY0_SIZE];
	char		*charPtr;
	WS_INVENTORY_RECORD	oldEntry;

	/* Copy the key data to somewhere that can be overwritten */
	charPtr = (char *)entry;
	for (i=0; i<KEY0_SIZE; i++)
		keyBuffer[i] = *charPtr++;

	/* Figure out the data buffer size */
	dataLength = sizeof(WS_INVENTORY_RECORD);

	/* Find the item matching the specification */
	status = BTRV(BT_GET_EQUAL, positionBlock, (char *)&oldEntry, (int *)&dataLength, keyBuffer, 0);

	return(status);
}

int InsertItem(WS_INVENTORY_RECORD *entry)
{
	int	status;
	int	dataLength;
	char	keyBuffer[KEY0_SIZE];

	/* Figure out the data buffer length */
	dataLength = sizeof(WS_INVENTORY_RECORD);

	/* Call Btrieve with Insert request */
	status = BTRV(BT_INSERT, positionBlock, (char *)entry, &dataLength, keyBuffer, 0);
	return(status);
}

int UpdateItem(WS_INVENTORY_RECORD *entry)
{
	int	status;
	int	dataLength;
	char	keyBuffer[KEY0_SIZE];

	/* Figure out the data buffer length */
	dataLength = sizeof(WS_INVENTORY_RECORD);

	/* Call Btrieve with Update request */
	status = BTRV(BT_UPDATE, positionBlock, (char *)entry, &dataLength, keyBuffer, 0);
	return(status);
}

int CloseDataFile(void)
{
	char			keyBuffer[KEY0_SIZE];
	int			bufferLength;
	WS_INVENTORY_RECORD	entry;
	int			status;

	/* Call Btrieve with Close operation */
	status = BTRV(BT_CLOSE, positionBlock, (char *)&entry, &bufferLength, keyBuffer, 0);

	return(status);
}

