/*********************************/
/*                               */
/*           RENAMER             */
/*                               */
/*   generates a Rename-Batch-   */
/*    File of an input file      */
/*             list              */
/*                               */
/*    J. Nagasaki Jun. 2003      */
/*                               */
/*********************************/


#define		FILECHAR 	40				// 40 chars for file names
#define		EXTCHAR 	8				// 8 chars for file name extension
#define		MAXFILES 	9999			// Max number of files to be renamed in list
#define		CHARERROR 	99				// "Error" Flag "99"

#include	<stdio.h>
#include	<string.h>					// For functions "strlen", "strcpy", "strncat"

char		zext[8];					// Global string for "zero-extension"

const char 	zero1[2] = "0";
const char 	zero2[3] = "00";
const char	zero3[4] = "000";
const char	zero4[5] = "0000";

/*----------------------------------------------------------------------*/

main (argc, argv)

int		argc;							// Number of arguments
char	*argv[];						// Argument strings (filenames)

{
	int		i, j, k, end, end2;			// Multipurpose counters and flags
	int		exten;						// Extension flag and pointer
	int		filenum;					// Number of Files of 'infile'
	char	c, c1;						// Dummy characters
	char	correct;					// Dialog flag
	char	instring[FILECHAR];
	char	infilename[FILECHAR];
	char	outfilename[FILECHAR];
	char	filelist[MAXFILES][FILECHAR];
	char	extension[MAXFILES][EXTCHAR];
	char	letter[FILECHAR];			// Desired new file name string
	long	startnum;					// Starting renaming number
	long	maxnum;						// Mantissa number
	long	endnum;						// Ending renamung number
	char	errflag[MAXFILES];			// "Possible rename error" flag
	char	extcount;					// Number of extensions of file
	char 	*p, *chr;					// Pointers (Arguments and characters)
	unsigned char ch;

	FILE	*infile, *outfile;

/*----------------------------------------------------------------------*/

	/* Check arguments */

	if (argc < 2)
	{
		fprintf (stderr, "\nRENAMER - written 2002, 2003 by J. Nagasaki\n\n");
		fprintf (stderr, "Usage:\n");
		fprintf (stderr, "renamer <filelist>\n");
		fprintf (stderr, "Output: 'renfiles.bat'\n\n");
		fprintf (stderr, "Type 'renamer -h' for short description\n\n");
		exit (0);
	}

	fprintf (stderr, "\n");

	p = argv[1];
	i = end = 0;

	while ((i <= FILECHAR) && (end == 0))
	{
		infilename[i] = *p;

		if (*p == '\0') end = 1;

		i++;
		p++;
	}
	infilename[FILECHAR-1] = '\0';

	if (infilename[0] == '-')
	{
		if ((infilename[1] == 'h') || (infilename[1] == 'H'))
		{
			fprintf (stderr, "==============================================================================\n");
			fprintf (stderr, "                   RENAMER - written 2002, 2003 by J. Nagasaki\n");
			fprintf (stderr, "==============================================================================\n\n");
			fprintf (stderr, "Purpose: Renaming files of a directory into an alphabetical list order.\n");
			fprintf (stderr, "Input:   Text file list of files to be renamed.\n");
			fprintf (stderr, "Output:  Batch file which contains renaming commands ('renfiles.bat').\n");
			fprintf (stderr, "\nDescription:\n");
			fprintf (stderr, "This program generates an executeable M$-DOS-Batch-file which renames a list\n");
			fprintf (stderr, "of files to new file names which are beginning with a user-stated string and\n");
			fprintf (stderr, "a following running number. The start of this number is also determineable\n");
			fprintf (stderr, "by the user. This is performed by a short dialog.\n");
			fprintf (stderr, "The input file must contain the file name list in the order to be renamed.\n");
			fprintf (stderr, "The file names must be entered line by line.\n\n");
			fprintf (stderr, "Note:\n");
			fprintf (stderr, "Even if the Output batch file contains the correct M$-DOS-File names\n");
			fprintf (stderr, "some characters of the names may not be interpreteable in a batch file.\n");
			fprintf (stderr, "For this reason it is recommended to open the batch file first with a text\n");
			fprintf (stderr, "editor and look for warnings before executing it.\n");
			fprintf (stderr, "In this case all regarding files should be renamed 'by hand'.\n");
			fprintf (stderr, "Forbidden characters: All national letters, '%%', '*', '(', ')', etc.\n");
			fprintf (stderr, "Last entry must be end with <RETURN>. Avoid empty lines!\n");

			exit (0);
		}

		else
		{
			fprintf (stderr, "ERROR: Unknown option '-%c'\n\n", infilename[1]);
			no_output();
			exit (1);
		}
	}

	infile = fopen(infilename, "r");

	if (!infile)
	{
		fprintf (stderr, "ERROR: File '%s' not found!\n\n", infilename);
		exit (1);
	}


	// Read file list into 'filelist'

	end = 0;
	i = 1;

	while (end == 0)
	{
		chr = fgets (instring, FILECHAR, infile);

		errflag[i] = 0;

		if (chr == '\0')
		{
			end = 1;
		}

		else
		{
			for (j = 0; j <= FILECHAR; j++)
			{
				filelist[i][j] = instring[j];

				if (instring[j] == '\n')
					filelist[i][j] = '\0';	// make end of string
			}

			if (filelist[i][0] == 0x20)		// space at beginning
			{
				fprintf (stderr, "\nERROR: First character in line %d is <SPACE>\n", i);
				no_output();
				exit(1);
			}

			else
			{
				// Check for "forbidden" characters

				end2 = j = 0;

				while (end2 == 0)
				{
					ch = filelist[i][j];

					if (ch == '\0')
					{
						end2 = 1;
					}

					else
					{
						if ((ch == 0x8e) || (ch == 0x99) || (ch == 0x9a) ||	// 'Ä' 'Ö' 'Ü'
							(ch == 0x84) || (ch == 0x94) || (ch == 0x81) ||	// 'ä' 'ö' 'ü'
							(ch ==  '%') || (ch ==  '!') || (ch == 0x22) ||  	// '"'
							(ch ==  '$') || (ch ==  '#') || (ch == '&')  ||
							(ch ==  '(') || (ch ==  ')') || (ch == '*')  ||
							(ch == 0xe1) || (ch ==  ',') || (ch == '^'))	// 'ß'
						{
						    errflag[i] = CHARERROR;						// WARNING output comes later!
						}

					}
					j++;
				}

			}
		}

		i++;
	}

	filenum = i - 1;

	if (filenum == 0)
	{
		fprintf (stderr, "ERROR: No Files found in '%s'\n", infilename);
		no_output();
		exit (2);
	}

	// Extracting file name extensions

	for (i = 1; i < filenum; i++)
	{
		exten = 0;
		extcount = 0;
		extension[i][0] = '\0';
		j = k = end = 0;

		while ((j < FILECHAR) && (end == 0))
		{
			if (exten != 0)
			{
				extension[i][k] = filelist[i][j];
				k++;
			}

			if (filelist[i][j] == '\0')
			{
				end = 1;
				extension[i][k] = '\0';
			}

			else if (filelist[i][j] == '.')
			{
				exten = j;
				extcount++;
				k = 0;
			}
			j++;
		}

		if (exten != 0)
		{
			filelist[i][exten] = '\0';	// Kill extension in filelist
		}

		else
		{
			fprintf (stderr, "WARNING: File '%s' has no extension.\n\n", filelist[i]);
		}

		if (extcount > 1)
		{
			fprintf (stderr, "WARNING: File '%s.%s' has more than one extension.\n\n", filelist[i], extension[i]);
		}

		if (errflag[i] == CHARERROR)
		{
			fprintf (stderr, "WARNING: File '%s", filelist[i]);
		   	if (exten != 0)
			   fprintf (stderr, ".%s", extension[i]);
		  	fprintf (stderr, "' contains characters which may not\n");
			fprintf (stderr, "         be interpretable in batch file.\n\n");
		}
	}


	// User Dialog of desired new file names

	correct = 0;

	while (correct == 0)
	{
		fprintf (stderr, "\nEnter desired renaming file name letter(s): "); // Leading string
		scanf("%s", letter);

		fprintf (stderr, "Enter desired renaming start number: ");
		scanf("%d", &startnum);

		maxnum = 0;
		c1 = '*';			// Dummy character
		while (c1 == '*')
		{
			while ((maxnum < 1) || (maxnum > 4))
			{
				fprintf (stderr, "Enter desired number of chars per numbering (1 - 4): ");
				scanf("%d", &maxnum);
			}

			fprintf (stderr, "\n");

			endnum = startnum + filenum - 2;

			zeroextend (startnum, maxnum);		// convert startnum into global string 'zext'
			fprintf (stderr, "MESSAGE: Rename file names to '%s%s' ... ", letter, zext);
			zeroextend (endnum, maxnum);			// convert endnum into global string 'zext'
			fprintf (stderr, "'%s%sd' [Y] ?", letter, zext);

			if (((endnum > 999)  && (maxnum < 4)) ||
			    ((endnum > 99)   && (maxnum < 3)) ||
			    ((endnum > 9)    && (maxnum < 2)))
			{
				fprintf (stderr, "\nWARNING: Numbering exceeds number of chars!");

				fflush(stdin);

				c = '*';
				while ((c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N'))
				{
					fprintf (stderr, "\nMESSAGE: Continue anyway [Y/N]? ");
					c = getche();
				}

				fflush(stdin);

				if ((c == 'y') || (c == 'Y') || (c == 0xd)) c1 = '1';
				else
				{
					maxnum = 0;	// reset input
					fprintf (stderr, "\n");
				}
			}

			else
			{
				c1 = '1';
			}
		}

		fflush(stdin);

		c = '*';			// Dummy character
		while ((c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N') && (c != 0xd)) 	// 0xd == '\n'
		{
			c = getche();
		}

		fflush(stdin);
		if ((c == 'y') || (c == 'Y') || (c == 0xd)) correct = 1;
	}


	// Generating Rename-Batch-File

	outfile = fopen ("renfiles.bat", "r");

	fflush (stdin);

	if (outfile)
	{
		c = '*';
		while ((c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N'))
		{
			fprintf (stderr, "\nWARNING: 'renfiles.bat' existing! Overwrite [Y/N]? ");
			c = getche();
		}

		fprintf (stderr, "\n");

		if ((c == 'n') || (c == 'N'))
		{
			fprintf (stderr, "RENAMER terminated.\n");
			no_output();
			exit (10);
		}

		fflush (stdin);
	}

	outfile = fopen ("renfiles.bat", "w");

	fprintf (outfile, "rem =========================================================================\n");
	fprintf (outfile, "rem                 RENFILES.BAT - generated by RENAMER.EXE\n");
	fprintf (outfile, "rem                     Written 2002, 2003 by J. Nagasaki\n");
	fprintf (outfile, "rem =========================================================================\n\n");
	fprintf (outfile, "rem -------------------------------------------------------------------------\n");
	fprintf (outfile, "rem FIRST STAGE:\n");
	fprintf (outfile, "rem Rename files into dummy file names to prevent double names\n");
	fprintf (outfile, "rem -------------------------------------------------------------------------\n\n");

	j = 0;

	for (i = 1; i < filenum; i++)
	{
		if (errflag[i] == CHARERROR)
		{
			fprintf (outfile, "\nrem *** WARNING ***\n");
		   	fprintf (outfile, "rem Next file may not be renameable, because it contains characters\n");
			fprintf (outfile, "rem which may not be interpreteable by executing this batch file\n");
		}

		fprintf (outfile, "  ren %s", filelist[i]);
		if (extension[i][0] != '\0')
		{
			fprintf (outfile, ".%s", extension[i]);
		}

		zeroextend (j, maxnum);
		fprintf (outfile, " @@%s", zext);
		if (extension[i][0] != '\0')
		{
			fprintf (outfile, ".%s", extension[i]);
		}

		fprintf (outfile, "\n");
		if (errflag[i] == CHARERROR)
			fprintf (outfile, "\n");

		j++;
	}

	fprintf (outfile, "\nrem -----------------------------------------------------------------------\n");
	fprintf (outfile, "rem SECOND STAGE:\n");
	fprintf (outfile, "ren Rename dummy names to desired file names\n");
	fprintf (outfile, "rem -------------------------------------------------------------------------\n\n");

	j = 0;
	k = startnum;

	for (i = 1; i < filenum; i++)
	{
		zeroextend (j, maxnum);
		fprintf (outfile, "  ren @@%s", zext);
		if (extension[i][0] != '\0')
		{
			fprintf (outfile, ".%s", extension[i]);
		}

		zeroextend (k, maxnum);
		fprintf (outfile, " %s%s", letter, zext);
		if (extension[i][0] != '\0')
		{
			fprintf (outfile, ".%s", extension[i]);
		}

		fprintf (outfile, "\n");

		j++;
		k++;
	}

	fprintf (stderr, "\nMESSAGE: 'renfiles.bat' successful generated.\n");
}

//-------------------------------- SUBS --------------------------------------------------

int no_output()
{
	fprintf (stderr, "No Output file generated.\n\n");
}


int zeroextend (int number, long maxchr) 	//zext is global output!
{
	int			i, j, k;
	char		c[8];

	sprintf (c, "%d", number);		// convert int 'number' to string 'c'

	strcpy (zext, c);				// copy 'c' to `zext'

	i = strlen(c);

	if (number == 0)
	{
		if      (maxchr == 1) strcpy (zext, zero1);	// Fill 'zext' with "0"
		else if (maxchr == 2) strcpy (zext, zero2);	// Fill 'zext' with "00"
		else if (maxchr == 3) strcpy (zext, zero3);	// Fill 'zext' with "000"
		else if (maxchr == 4) strcpy (zext, zero4);	// Fill 'zext' with "0000"
	}

	else if (i < 2)
	{
		if (maxchr == 2)
		{
			strcpy (zext, zero1);	// Fill 'zext' with "0"
			strncat (zext, c, 8);	// Extend 'zext' with 'c'
		}
		else if (maxchr == 3)
		{
			strcpy (zext, zero2);	// Fill 'zext' with "00"
			strncat (zext, c, 8);	// Extend 'zext' with 'c'
		}
		else if (maxchr == 4)
		{
			strcpy (zext, zero3);	// Fill 'zext' with "000"
			strncat (zext, c, 8);	// Extend 'zext' with 'c'
		}
	}

	else if (i < 3)
	{
		if (maxchr == 3)
		{
			strcpy (zext, zero1);	// Fill 'zext' with "0"
			strncat (zext, c, 8);	// Extend 'zext' with 'c'
		}
		else if (maxchr == 4)
		{
			strcpy (zext, zero2);	// Fill 'zext' with "00"
			strncat (zext, c, 8);	// Extend 'zext' with 'c'
		}
	}

	else if ((i < 4) && (maxchr == 4))
	{
		strcpy (zext, zero1);		// Fill 'zext' with "0"
		strncat (zext, c, 8);		// Extend 'zext' with 'c'
	}
}


