/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: Identify.c
 *	Created ..: Thursday 02-May-91 15:00
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	02-May-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

	/* The file types we know. */

enum	{	TYPE_DIR,TYPE_FILE,TYPE_ICON,
		TYPE_TEXT,
		TYPE_C,TYPE_H,
		TYPE_ASM,TYPE_I,
		TYPE_MOD,
		TYPE_REXX,
		TYPE_BASIC,
		TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
		TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
		TYPE_OBJECT,TYPE_LIB,
		TYPE_EXECUTABLE,
		TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
		TYPE_GIF,TYPE_ILBM,TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,
		TYPE_IMPLODER,TYPE_POWERPACKER,
		TYPE_ARC,TYPE_LHARC,TYPE_ZOO,TYPE_ZIP,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
	};

	/* A structure containing both a file name suffix and the
	 * approriate file type.
	 */

struct Suffix
{
	UBYTE	*Name;
	UBYTE	 Type;
};

	/* A table of valid ASCII characters (7 bits). */

STATIC BYTE ID_ValidTab[256] =
{
	0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
	0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

	/* A table of clearly invalid ASCII characters (8 bits). */

STATIC BYTE ID_InvalidTab[256] =
{
	1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
	1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

	/* Some file name suffixes for text files and the approriate
	 * file types.
	 */

STATIC struct Suffix TextSuffix[] =
{
	".C",	TYPE_C,
	".CP",	TYPE_C,
	".CC",	TYPE_C,
	".H",	TYPE_H,
	".ASM",	TYPE_ASM,
	".A",	TYPE_ASM,
	".S",	TYPE_ASM,
	".I",	TYPE_I,
	".BAS",	TYPE_BASIC,
	".GFA",	TYPE_BASIC,
	".REXX",TYPE_REXX,
	".CED",	TYPE_REXX,
	".VLT",	TYPE_REXX,
	".CPR",	TYPE_REXX,
	".TxEd",TYPE_REXX,
	".TEX",	TYPE_TEX,
	".STY",	TYPE_TEX,
	".MF",	TYPE_METAFONT,
	".MOD",	TYPE_MOD,
	".DEF",	TYPE_MOD
};

	/* Some more file name suffixes for executable files and the
	 * approriate file types.
	 */

STATIC struct Suffix ExecutableSuffix[] =
{
	".device",	TYPE_DEVICE,
	".library",	TYPE_LIBRARY,
	"FileSystem",	TYPE_FILESYS,
	"Handler",	TYPE_HANDLER
};

	/* This list contains the names of all icon files which can be
	 * attached to the files to be identified. The flag byte indicates
	 * whether an icon is available or not.
	 */

STATIC UBYTE *FileTypes[] =
{
	NULL,
	NULL,
	"Workbench icon file",
	"ASCII text file",
	"`C' source code file",
	"`C' header file",
	"Assembly language source code file",
	"Assembly language include file",
	"Modula-2/Oberon source code file",
	"ARexx script file",
	"Basic source code",
	"TeX document file",
	"Metafont font file",
	"Generic font file",
	"Packed TeX font file",
	"TeX device independent output file",
	"PasTeX font library file",
	"Manx 3.x object code file",
	"Manx 5.x object code file",
	"Manx 3.x library file",
	"Manx 5.x library file",
	"AmigaDOS object code file",
	"AmigaDOS object code library file",
	"AmigaDOS executable file",
	"System library file",
	"System device file",
	"AmigaDOS filing system handler file",
	"AmigaDOS handler file",
	"GIF image file",
	"IFF-ILBM image file",
	"IFF-ANIM animation file",
	"IFF-8SVX sound file",
	"IFF-SMUS score file",
	"IFF-FTXT text file",
	"IFF-PREF preferences file",
	"IFF-TERM `term' configuration file",
	"Imploder data output file",
	"PowerPacker data output file",
	"Arc archive file",
	"LhArc archive file",
	"Zoo archive file",
	"PKZip archive file",
	"DMS disk archive file",
	"Warp disk archive file",
	"Zoom disk archive file"
};

	/* Identify(UBYTE *Name):
	 *
	 *	Simple routine to identify a file type by looking at
	 *	its first 400 bytes. If successful a comment is
	 *	attached to the file describing the file type.
	 */

VOID
Identify(UBYTE *Name)
{
	ULONG	*Buffer;
	UBYTE	 Type = TYPE_FILE;
	SHORT	 i,Len = strlen(Name);

		/* Allocate a buffer for the first 400 bytes of the
		 * file.
		 */

	if(Buffer = (ULONG *)AllocVec(400,MEMF_PUBLIC))
	{
		BPTR File,Size;

			/* Open the file. */

		if(File = Open(Name,MODE_OLDFILE))
		{
				/* Read the first 400 bytes. */

			if((Size = Read(File,Buffer,400)) >= sizeof(ULONG))
			{
					/* Examine the first longword. */

				switch(Buffer[0])
				{
					case 0x03E7:	Type = TYPE_OBJECT;
							break;

					case 0x03F3:	Type = TYPE_EXECUTABLE;
							break;

					case 0x03FA:	Type = TYPE_LIB;
							break;

					case 0xF7593647:Type = TYPE_TEXFONT;
							break;

					case 0xF7020183:Type = TYPE_TEXDVI;
							break;

					case 0xF7832020:Type = TYPE_GF;
							break;

					case 0x504B0304:Type = TYPE_ZIP;
							break;

					default:	break;
				}

					/* No match yet, see if it's an
					 * ASCII file.
					 */

				if(Type == TYPE_FILE)
				{
					UBYTE	*CharBuffer = (UBYTE *)Buffer;
					SHORT	 Count = 0;

					for(i = 0 ; i < Size ; i++)
					{
						if(ID_ValidTab[CharBuffer[i]])
							Count++;
						else
						{
							if(ID_InvalidTab[CharBuffer[i]])
							{
								Count = 0;

								break;
							}
						}
					}

						/* If more than 75% of the
						 * characters in the first
						 * 400 bytes are legal
						 * ASCII characters this
						 * file is supposed to be
						 * a text file.
						 */

					if(Count > 3 * (Size / 4))
						Type = TYPE_TEXT;
				}

					/* Still no match, have another try... */

				if(Type == TYPE_FILE)
				{
					if((Buffer[0] & 0xFFFF0000) == 0x1A080000)
						Type = TYPE_ARC;
					else
					{
						if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
							Type = TYPE_LHARC;
						else
						{
							switch(Buffer[0] & 0xFFFF0000)
							{
								case 0x434A0000:	Type = TYPE_NEWMANX;
											break;

								case 0x414A0000:	Type = TYPE_OLDMANX;
											break;

								case 0x636A0000:	Type = TYPE_NEWMANXLIB;
											break;

								case 0x616A0000:	Type = TYPE_OLDMANXLIB;
											break;

								case 0xF5000000:	Type = TYPE_BASIC;
											break;

								case 0xE3100000:	Type = TYPE_ICON;
											break;

								default:		break;
							}
						}
					}
				}

				if(Type == TYPE_FILE)
				{
					switch(Buffer[0])
					{
						case 'FLIB':	Type = TYPE_FLIB;
								break;

						case 'FORM':	switch(Buffer[2])
								{
									case 'ILBM':	Type = TYPE_ILBM;
											break;

									case 'ANIM':	Type = TYPE_ANIM;
											break;

									case '8SVX':	Type = TYPE_8SVX;
											break;

									case 'SMUS':	Type = TYPE_SMUS;
											break;

									case 'FTXT':	Type = TYPE_FTXT;
											break;

									case 'PREF':	Type = TYPE_PREFS;
											break;

									case 'TERM':	Type = TYPE_TERM;
											break;
								}

								break;

						case 'IMP!':	Type = TYPE_IMPLODER;
								break;

						case 'PP20':	Type = TYPE_POWERPACKER;
								break;

						case 'DMS!':	Type = TYPE_DMS;
								break;

						case 'Warp':	Type = TYPE_WARP;
								break;

						case 'ZOOM':	Type = TYPE_ZOOM;
								break;

						case 'ZOO ':	Type = TYPE_ZOO;
								break;

						case 'GIF8':	Type = TYPE_GIF;
								break;
					}
				}

					/* Take a look at the file name
					 * suffixes.
					 */

				switch(Type)
				{
					case TYPE_TEXT:
							for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
							{
								Size = strlen(TextSuffix[i] . Name);

								if(Len >= Size)
								{
									if(!StrCmp(&Name[Len - Size],TextSuffix[i] . Name))
									{
										Type = TextSuffix[i] . Type;
										break;
									}
								}
							}

							break;

					case TYPE_EXECUTABLE:
							for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
							{
								Size = strlen(ExecutableSuffix[i] . Name);

								if(Len >= Size)
								{
									if(!StrCmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
									{
										Type = ExecutableSuffix[i] . Type;
										break;
									}
								}
							}

							break;

					case TYPE_OBJECT:
							if(Len >= 4)
							{
								if(!StrCmp(&Name[Len - 4],".LIB"))
									Type = TYPE_LIB;
							}

							break;

					default:	break;
				}
			}

			Close(File);
		}

		FreeVec(Buffer);
	}

	if(Type != TYPE_FILE && FileTypes[Type])
		SetComment(Name,FileTypes[Type]);

	if(Type != TYPE_EXECUTABLE)
		SetProtection(Name,FIBF_EXECUTE);
}
