/*
 * Suchen einer Zeichenkette in Dateien
 * (c) Jens Mller 1993
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ext.h>
#include <ctype.h>


void wait_key(void)
{
	printf("\nPress any key...");
	getch();
	printf("\n");
	exit(0);
}


void help(void)
{
	printf("Call:  String  File");
	wait_key();
}


void find_str(char *str, char *filespec, size_t fsize)
{
	int		handle, found = 0, row;
	char	*buf, *p, *s, *row_ptr;
	size_t	bytes, i, j;

	handle = open(filespec, O_RDONLY);
	if (handle == EOF)
	{
		printf("Error opening %s!\n", filespec);
		return;
	}

	buf = malloc(fsize);
	if (buf == NULL)
	{
		printf("Not enoght memory for %s!\n", filespec);
		close(handle);
		return;
	}

	bytes = read(handle, buf, fsize);
	if (bytes != fsize)
	{
		printf("Error reading %s!\n", filespec);
		close(handle);
		free(buf);
		return;
	}

	close(handle);

	/* String suchen */
	strupr(str);
	row = 1;
	row_ptr = buf;
	for (i = 0; i < fsize; i++)
	{
		p = &buf[i];
		s = str;
		while (*s && (toupper(*p) == *s))
		{
			p++;
			s++;
		}

		if (*s == '\0')
		{
			found = 1;
			printf("\nString found in row %d of file %s:\n",
				row, filespec);

			/* Zeile bis Suchstring ausgeben */
			p = row_ptr;
			while (p != &buf[i])
				putch(*p++);

			/* Suchstring invers ausgeben */
			printf("\x1Bp");
			for (j = 0; j < strlen(str); j++)
				putch(*p++);
			printf("\x1Bq");

			/* Rest der Zeile ausgeben */
			while (*p != '\n')
				putch(*p++);
			printf("\n");
		}

		if (buf[i] == '\n')
		{
			row++;
			row_ptr = &buf[i + 1];
		}
	}

	if (found == 0)
		printf("String not found in %s.\n", filespec);

	free(buf);
}


void find_file(char *str, char *filespec)
{
	int		status;
	char	*p, *h;
	struct ffblk datei;

	strupr(filespec);

	p = filespec;
	if (filespec[1] == ':')
		p = &filespec[2];
	if ((h = strrchr(p, '\\')) != NULL)
		p = &h[1];

	status = findfirst(filespec, &datei,
		FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH);
	if (status == EOF)
	{
		printf("File not found!\n");
		wait_key();
	}

	while (status != EOF)
	{
		if (kbhit() && (getch() == 3))		/* ^C gedrckt */
		{
			printf("^C...\n");
			wait_key();
		}

		if (datei.ff_fsize)
		{
			strcpy(p, datei.ff_name);
			find_str(str, filespec, datei.ff_fsize);
		}

		status = findnext(&datei);
	}
}


void main(int argc, char *argv[])
{
	char	str[128];
	char	*str_ptr;
	char	filespec[128];
	char	*filespec_ptr;
	char	*p, c;

	if (argc > 3)
		help();

	if (argc > 1)
		str_ptr = argv[1];
	else
	{
		printf("String : ");
		gets(str);
		if (str[0] == '\0')			/* leerer String */
			help();

		/* Leerzeichen und Tabs vor dem String entfernen */
		p = str;
		while ((*p == ' ') || (*p == '\t'))
			p++;
		str_ptr = p;

		/* Stringende suchen */
		while (*p && (*p != '\n') && (*p != '\r'))
			p++;

		/* Leerzeichen und Tabs hinterm String entfernen */
		while (((c = *(p - 1)) == ' ') || (c == '\t'))
			p--;
		*p = '\0';

		/* falls String in Gnsefchen */
		if ((*str_ptr == '\"') && (*(p - 1) == '\"'))
		{
			str_ptr++;
			*--p = '\0';
		}
	}

	if (argc > 2)
		filespec_ptr = argv[2];
	else
	{
		printf("File(s): ");
		gets(filespec);
		if (filespec[0] == '\0')
			help();
		filespec_ptr = filespec;
	}

	find_file(str_ptr, filespec_ptr);
	wait_key();
}

