/*
version: [$Id: menu_edit.c,v 5.123 1995/01/18 01:24:58 hitman Exp $]
purpose: This program is used to convert text menus to binary menus that the bbs can read and use.
syntax:	menu_edit [-q] menu_to_edit
updates: All updates are handled by RCS
author: The Hitman 1994
*/


#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#ifndef __MSDOS__
#	include "bbs_director.h"
#	include "menu_info.h"
#else				/* not_MSDOS */
#	include "..\src\bbs_dire.h"
#	include "..\src\menu_inf.h"
#endif				/* MSDOS */

#define QUIET	65

int
main(int argc, char **argv)
{
	FILE           *outputfile,	/* I am the binary file for the BBS */
	               *inputfile;	/* I am the text file for editing */

	char            input = '0';	/* I read in the characters from the */
	/* input file */
	char            filename[MAXLENGTH] =
	{0};			/* I represent a filename */

	int             column = 0;	/* I keep track of what column we are
					   on */
	int             row = 0;/* I keep track of the letter of the word we
				   are on. */
	int             line = 0;	/* I mark the line in the menu file
					   that we are on.  The max is
					   MAXLINES */
	int             Mode = 0;	/* I keep track of the mode of this
					   program */
	int             Count = 0;	/* Incrementing for the menu
					   filenames. */
	int             cnt = 0;/* Incrementing for the generic things. */

	MENU_struct     menu[MAXLINES];	/* I keep track of the menus and
					   other menu related information. */
	MENU_struct    *menu_ptr;	/** A pointer to the menu variable in memory **/

	/* Functions used in this program */
	extern int      display_bbs_version(void);
	extern char    *menu_data_filename(char *);
	extern char    *menu_text_filename(char *);

	/** Cleans up some warnings **/
#ifdef OSF1
	extern char    *strcpy(char *, const char *);
	extern char    *strcat(char *, const char *);
#endif				/* OSF1 */

	/** Check for the right number of input **/
	if (argc <= 1)
	{
		fprintf(stderr, "syntax: %s -[q] menu_to_compile\n", argv[0]);
		fprintf(stderr, "\t-quiet\tenables no printing of version\n");
		fprintf(stderr, "\nIt is not nessesary to add the trailing\n" \
			"extention to the end of the filename.  This\n" \
			"program will do that for you.\n\n");
		exit(EXIT_FAILURE);
	}			/* if */
	if (argc >= 2)
	{
#if DEBUG
		fprintf(stderr, "** %s: Few comparison Tables **\n", __FILE__);
		fprintf(stderr, "**\targv[1] = %s; strcmp (argv[1], \"-q\") = %d; strcmp (argv[1], \"-quiet\") = %d **\n", argv[1], (strcmp(argv[1], "-q")), (strcmp(argv[1], "-quiet")));
		fprintf(stderr, "**\t(strcmp (argv[1], \"-q\") || strcmp (argv[1], \"-quiet\")) = %d **\n", (strcmp(argv[1], "-q") || strcmp(argv[1], "-quiet")));
		fprintf(stderr, "**\tstrncmp (argv[1], \"-q\", 1) = %d **\n", (strncmp(argv[1], "-q", 1)));
#endif				/* DEBUG */
		if (strncmp(argv[1], "-q", 1) == TRUE)
		{
#if DEBUG
			fprintf(stderr, "** %s: Setting Mode to QUIET **\n", __FILE__);
#endif				/* DEBUG */
			Mode = QUIET;
		};		/* if_option_quiet */
	};			/* if_arg_great_two */

/* Check if quiet mode is enabled; if mode quiet then don't print the version information */
	if (Mode != QUIET)
	{
		/* Print out some version information */
		puts("For use with:");
		display_bbs_version();
	};			/* if_not_quiet */

#if DEBUG
	fprintf(stderr, "** %s: START Menu Compiling **\n", __FILE__);
#endif				/* DEBUG */
	/* set the count argument equal to the number of elements on the
	   command line */
	Count = argc;
	for (cnt = 0; Count > cnt; cnt++)
	{
		/* check for the zeroth argument; if cnt equals zero continue */
		if (cnt == 0)
		{
			continue;
		}		/* if_cnt_zero */

		/* Do checking for the Mode as QUIET; if mode and cnt is
		   equal to one is quiet just continue in the loop */
#if DEBUG
		fprintf(stderr, "** %s: Doing checking on the mode and count. **\n", __FILE__);
		fprintf(stderr, "**\tMode = %d; QUIET = %d; Count = %d; cnt = %d **\n", Mode, QUIET, Count, cnt);
		fprintf(stderr, "**\t(Mode == QUIET) = %d; (cnt == 1) = %d **\n", (Mode == QUIET), (cnt == 1));
#endif				/* DEBUG */
		if ((Mode == QUIET) && (cnt == 1))
			continue;


		/* Since the syntax is correct go ahead and assign the
		   filenames.  The filename will not have the .menu on it so
		   I can just append the .menu and the .dat to the end of
		   these files.  This will make the menu file definitions a
		   lot easier. */
		/* This file is a text file, that will be read from the
		   beginning each time.  This file is a templete for the
		   menus created by this program, all comments are striped */
		strcpy(filename, menu_text_filename(argv[cnt]));
#if DEBUG
		fprintf(stderr, "** %s: Starting the opening of the text input file **\n", __FILE__);
		fprintf(stderr, "** %s: argv[cnt] = %s, filename = %s **\n", __FILE__, argv[cnt], filename);
#endif
/* read the menu text templete only, we will not need to write to this one */
		if ((inputfile = fopen(filename, "r")) == NULL)
		{
			/* If the text file is not found, tell the user that
			   they must create the menu text file first before
			   compiling it. */
			fprintf(stderr, "%s: %s: No such file or directory\n", argv[0], filename);

			exit(EXIT_FAILURE);
		}		/* if */
		/** This file is a binary file, that will be written from the */
		/* beginning each time.  No appending * */
		strcpy(filename, menu_data_filename(argv[cnt]));
#if DEBUG
		fprintf(stderr, "** %s: Starting the opening of the biniary output file **\n", __FILE__);
		fprintf(stderr, "** %s: argv[cnt] = %s, filename = %s **\n", __FILE__, argv[cnt], filename);
#endif
		if ((outputfile = fopen(filename, "wb")) == NULL)
		{
			fprintf(stderr, "%s: %s: Need write permission\n", argv[0], filename);
			exit(EXIT_FAILURE);
		}		/* if */
		/** Make sure that both files are at the beginning **/
		fseek(outputfile, 0, SEEK_SET);
		fseek(inputfile, 0, SEEK_SET);

		/* Show this programs version number in relation to the
		   complete project */
#if DEBUG
		fprintf(stderr, "** %s: display version information for the bbs in general **\n", __FILE__);
#endif


		/* Let the user know what is going on */
		printf("Working on menu file: %s", filename);

		/* Before I start to read up the menus, I need to start on
		   column one then go from there. */
#if DEBUG
		fprintf(stderr, "** %s: reseting to the first column of the menu **\n", __FILE__);
#endif
		column = 1;
		row = 0;

		/* Point to the menu file with a pointer */
		menu_ptr = menu;

		/* Pad the entire block of variables with end of string
		   characters to initialize everything */
#if DEBUG
		fprintf(stderr, "** %s: Initializing the variables with end of string **\n", __FILE__);
#endif
		for (line = 0; line < MAXLINES; line++)
		{
			menu[line].index = (int) '\0';
			menu[line].keyword[0] = '\0';
			menu[line].description[0] = '\0';
			menu[line].information[0] = '\0';
			menu[line].other[0] = '\0';
		}
		line = 0;	/* Put the line back at zero, I was using it
				   temp */

		/** Start reading the file character by character and use the */
		/* character ":" for the seperators, unless it has a "\" */
		/* infront of it. * */
		while (!feof(inputfile))
		{
			input = '\0';	/** set the input clean with a null to make */
			/* the rest of the reading more reliable * */
			input = fgetc(inputfile);

			/* Print some status information to the user in the
			   form of the magic spinning cursor. */
			printf(" -\b\\\b|\b/\b\b");

#if DEBUG
			fprintf(stderr, "** %s: input = %c **\n", __FILE__, input);
			fprintf(stderr, "** %s: column = %d, row = %d, line = %d **\n", __FILE__, column, row, line);
#endif
			switch ((int) input)
			{
				/** I have found a comment please move to the next line **/
			case (int) '#':
				/** Move the file pointer to the beginning of the next line **/
				do
				{
					input = fgetc(inputfile);
					/** Lets print the comments to the screen **/
					fprintf(stdout, "%c", input);
				}
				while (input != '\n');	/* do */
				break;

				/** Column Seperator **/
			case (int) ':':
#if DEBUG
				fprintf(stderr, "** %s: found a \":\" go to the next column **\n", __FILE__);
#endif
				/** I passed a colon so I am now in the next column **/
				column++;
				/** I also want to return the row value back to */
				/* zero to start the next column.  Remember
				   at the */
				/* end of this loop we add one to the
				   variable row so */
				/* this negitive one will really be zero * */
				row = -1;
#if DEBUG
				fprintf(stderr, "** %s: NEXT ---------------------- **\n", __FILE__);
#endif
				break;

				/** Ignore all the nulls because I don't know what */
				/* to do with them. * */
			case (int) '\0':
#if DEBUG
				fprintf(stderr, "** %s: found a null just ignore **\n", __FILE__);
#endif
				break;

				/** Apon reaching a return character we are now on the next */
				/* line of the menu, I need to make this
				   known * */
			case (int) '\n':
#if DEBUG
				fprintf(stderr, "** %s: found the end of the line, marked by a return **\n", __FILE__);
#endif
				line++;	/* Increment the line number */
				column = 1;	/** when on a new line reset the column */
				/* that everything starts at, column 1 * */
				row = -1;	/* Also reset the row */
#if DEBUG
				fprintf(stderr, "** %s: NEXT ---------------------- **\n", __FILE__);
#endif
				break;

				/* I need to keep track of the number of
				   columns so I place the */
				/* menu options in the correct part of the
				   structure.  If I mess */
				/* this up I will be in real trouble. */
			default:
				/** Accounding to the current column place the */
				/* information in the variable. * */
#if DEBUG
				fprintf(stderr, "** %s: check the column and place the variable **\n", __FILE__);
#endif
				switch (column)
				{
					/** Column One is the index for the menu option **/
				case 1:
#if DEBUG
					fprintf(stderr, "** %s: column = %d so it's an index **\n", __FILE__, column);
#endif
					menu[line].index = (int) input;	/* the input is a char
									   so it needs to be
									   copied */
#if DEBUG
					fprintf(stderr, "** %s: menu[%d].index = %c **\n", __FILE__, line, menu[line].index);
#endif
					break;

					/** Column Two is the keyword, with the max of */
					/* MAXKEY letters in it.  If the
					   character go */
					/* past the maximum letters, just
					   ignore the */
					/* rest, maybe display a message * */
				case 2:
#if DEBUG
					fprintf(stderr, "** %s: column = %d : start working on the keyword **\n", __FILE__, column);
#endif
					if (row < MAXKEY)
					{
						menu[line].keyword[row] = input;
						menu[line].keyword[row + 1] = '\0';	/* set to null */
					}	/* if */
					else
					{
						/** Let the user know that the column is to wide but */
						/* don't kill anything * */
						fprintf(stderr, "%s: Warning: column %d, keyword is %d too long\n", \
							argv[0], column, (row - MAXKEY));
					}	/* else */
#if DEBUG
					fprintf(stderr, "** %s: menu[%d].keyword = %s **\n", __FILE__, line, menu[line].keyword);
#endif
					break;

					/* Column Three is for the
					   information on the */
					/* menu option.  All characters
					   longer then the */
					/* length of the block will be
					   ignored */
				case 3:
#if DEBUG
					fprintf(stderr, "** %s: column = %d, row = %d : start working on the description **\n", __FILE__, column, row);
#endif
					if (row < MAXLENGTH)
					{
						menu[line].description[row] = input;
						menu[line].description[row + 1] = '\0';	/* set to null */
					}	/* if */
					else
					{
						/** Let the user know that the column is to wide but */
						/* don't kill anything * */
						fprintf(stderr, "%s: Warning: column %d, description is %d too long\n", \
							argv[0], column, (row - MAXKEY));
					}	/* else */
#if DEBUG
					fprintf(stderr, "** %s: menu[%d].description = %s **\n", __FILE__, line, menu[line].description);
#endif
					break;

					/** This section is for regular menu information **/
				case 4:
#if DEBUG
					fprintf(stderr, "** %s: column = %d, row = %d : start working on the information **\n", __FILE__, column, row);
#endif
					if (row < MAXLENGTH)
					{
						menu[line].information[row] = input;
						menu[line].information[row + 1] = '\0';	/* set to null */
					}	/* if */
					else
					{
						/** Let the user know that the column is to wide but */
						/* don't kill anything * */
						fprintf(stderr, "%s: Warning: column %d, information is %d too long\n", \
							argv[0], column, (row - MAXKEY));
					}	/* else */
#if DEBUG
					fprintf(stderr, "** %s: menu[%d].information = %s **\n", __FILE__, line, menu[line].information);
#endif
					break;

					/** This section is for other information **/
				case 5:
#if DEBUG
					fprintf(stderr, "** %s: column = %d, row = %d : start working on the other **\n", __FILE__, column, row);
#endif
					if (row < MAXLENGTH)
					{
						menu[line].other[row] = input;
						menu[line].other[row + 1] = '\0';	/* set to null */
					}	/* if */
					else
					{
						/** Let the user know that the column is to wide but */
						/* don't kill anything * */
						fprintf(stderr, "%s: Warning: column %d, other is %d too long\n", \
							argv[0], column, (row - MAXKEY));
					}	/* else */
#if DEBUG
					fprintf(stderr, "** %s: menu[%d].other = %s **\n", __FILE__, line, menu[line].other);
#endif
					break;

				}	/* switch */
				break;
			}	/* switch */
			/** Advance to the next row, because you are about to grab */
			/* a new character * */
			row++;
		}		/* while */

		/** Write out the menu variable and all to the binary file. */
		/* I want to write only what is needed * */
		fwrite(menu, sizeof(MENU_struct), line, outputfile);
#if DEBUG
#	ifdef Linux
		fprintf(stderr, "** %s: sizeof (MENU_struct) = %d **\n", __FILE__, sizeof(MENU_struct));
#	endif			/* Linux */
#	ifdef OSF1
		/** Try to combine the following debuging statement. **/
		fprintf(stderr, "** %s: sizeof (MENU_struct) = %d **\n", __FILE__, (int) sizeof(MENU_struct));
#	endif			/* OSF1 */
#endif				/* DEBUG */


		/* After all the information has been written, please close
		   all files that where used.  Thanks... */
		fclose(inputfile);
		fclose(outputfile);
#if DEBUG
		fprintf(stderr, "** %s: print back the variables **\n", __FILE__);
		/* I am just useing the variable row here because I don't
		   want to introduce anymore variables for something more
		   than a Debuging statement */
		for (row = 0; row < MAXLINES; row++)
		{
			fprintf(stderr, "** %s: index = %c, keyword = %s, description = %s,\n\tinformation = %s, other = %s \n", \
				__FILE__, menu[row].index, menu[row].keyword, menu[row].description, menu[row].information, menu[row].other);
		}
#endif
		/* Everything is done so give the done sign */
		puts(" - Done");

	};			/* for_through_the_menus */
#if DEBUG
	fprintf(stderr, "** %s: END for loop **\n", __FILE__);
#endif				/* DEBUG */

	/* give some space */
	puts("");
	return (EXIT_SUCCESS);
}				/* main */
