#define CATCOMP_NUMBERS
#include "hotlist.module.strings"

#define _DOPUS_MODULE_DEF
#include <dopus/modules.h>

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <exec/exec.h>
#include <proto/exec.h>
#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>
#include <libraries/asl.h>
#include <clib/asl_protos.h>
#include <pragmas/asl_pragmas.h>
#include <clib/intuition_protos.h>
#include <pragmas/intuition_pragmas.h>
#include <clib/utility_protos.h>
#include <pragmas/utility_pragmas.h>

#include "ResourceNodes.h"

/**************************************************************************************/

extern struct SignalSemaphore *configsemaphore;		// From special modinit code.

/**************************************************************************************/

/*= Magic Numbers ====================================================================*/

#define MIN_OPUS_VERSION 55				// Minimum version of dopus5.library required.
#define MIN_EXEC_VERSION 37				// Minimum version of exec.library required.
#define PUDDLESIZE 5120					// Size of memory-pool puddles.
#define THRESHSIZE 4096					// Allocations above this size get own puddle.

#define HEPUDDLESIZE 5120				// -._ As above, but for memory pool used
#define HETHRESHSIZE 4096				// -'  exclusively for hotlist-entries.

#define INFORMUSERBUFFERSIZE 1024		// Buffer for writting InformUser() strings to.
#define COMMBUFFSIZE 1024				// Size of buffers for (ARexx) command strings.

#define PATHBUFFSIZE 512				// Size of buffers for file paths.
/*
#define NAMEBUFFSIZE 32					// Size of buffers for file names.
*/

#define HOTENTPATHLEN PATHBUFFSIZE		// Size of respective buffers for each
#define HOTENTNAMELEN 50				// HotEntry's path and name.

#define HOTTYPE_DIR  2					// Numbers representing different types.
//#define HOTTYPE_FILE 4					// These are also passed to Opus when
#define HOTTYPE_FILE 1					// These are also passed to Opus when
#define HOTTYPE_DEV  -2					// the file is added.
#define HOTTYPE_HOT  -4					// (For sub-hotlists).

#define GCS_SHARED 0					// Shared type for getConfigSemaphore()
#define GCS_EXCLUSIVE 1					// Exclusive type for getConfigSemaphore()

#define CONFIGVER 1						// Version of the config-file format.

#define DEFAULT_CONFIG "DOpus5:System/Hotlist.prefs"

#define CMD_TEMPLATE "NEW/S,CONFIG,LISTER/K"
enum {ARG_NEW,ARG_CONFIG,ARG_LISTER};

/*= Flags ============================================================================*/

#define IU_CANCEL 1						// For informUser().


/*= Non-Localized strings ============================================================*/
#define PORTNAME_FMT "dohotlist.%d"
#define PORTNAME_PREFIX "dohotlist."

/*= Macros ===========================================================================*/
#define TEXT_INTERNAL_ERROR DOpusGetString(locale,MSG_INTERNAL_ERROR)
#define dgs(A) DOpusGetString(locale,A)
#define TAGIF(expr,tag) ((expr) ? (tag) : (TAG_IGNORE))
#define TAGNOT(expr,tag) ((expr) ? (TAG_IGNORE) : (tag))

/*= Misc. TypeDefs ===================================================================*/
typedef struct hotent
{
	struct hotent *next;
	BOOL deleted;
	char name[HOTENTNAMELEN];
	char path[HOTENTPATHLEN];
	WORD type;
} HotEntry;

typedef struct configlistnode
{
	struct configlistnode *parent;	// Previous ConfigListNode.
	ResNode *rn;		// ResNode containing the filename.
	ResNode *rn_self;	// ResNode containing this ConfigListNode.
} ConfigListNode;

typedef struct
{
	int x;							// -.
	int y;							//  |_ Geometry used when
	int w;							//  |  openning a new lister.
	int h;							// -'  (-1 for all means "don't use")
} Snapshot;


/*= Pseudo-global variables ==========================================================-.
|| This is a re-entrant library so real global variables cannot be used.			  ||
|| Instead we allocate this structure and pass the pointer to it around.			  ||
||------------------------------------------------------------------------------------||
|| These must all default to NULL when allocated (MEMF_CLEAR must be given).		  ||
`-====================================================================================*/
typedef struct
{
	IPCData *ipc;						// -._ Copies of commonly used
	EXT_FUNC(func_callback);			// -'  values from Opus.

	BOOL new;							// TRUE if "new" switch given on command-line.
	char *config;						// Pointer to current config filename.
	char *originalconfig;				// Pointer to original config filename.
	ConfigListNode *conflist;			// 'Parent' config filenames list.

	ResNode_Data rnd;					// For ResourceNode routines.

	APTR hentspool;						// Memory pool for hotlist-entries.
	HotEntry *hentbase;					// First hotlist-entry in linked list, or NULL.

	struct MsgPort *msgport;			// Our message port.
	char mpname[32];					// Name of our message port.

	char lister[24];					// Handle of our lister (ASCII string).
	APTR listerhandle;					// Handle of our lister (APTR).

	Snapshot snap;						// Geometry used when openning a new lister.
	char parent[PATHBUFFSIZE];			// Original path of our lister, if any.

	struct ClockData time;

	ULONG notsigmask;					// Bitmask containing notification signal.
	BOOL notifyon;						// If TRUE we have notification ON.
	struct NotifyRequest notify;

} Hotlist_Data;

/*= IFF ID's =========================================================================*/

// MAKE_ID() below taken from iffparse.library's header file. Remove from here if
// it is also included.
#define MAKE_ID(a,b,c,d)	\
	((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

#define ID_DOHL		MAKE_ID('D','O','H','L')
#define ID_NAME		MAKE_ID('N','A','M','E')
#define ID_PATH		MAKE_ID('P','A','T','H')
#define ID_TYPE		MAKE_ID('T','Y','P','E')
#define ID_SNAP		MAKE_ID('S','N','A','P')
#define ID_VERS		MAKE_ID('V','E','R','S')
#define ID_TIME		MAKE_ID('T','I','M','E')

/*= Prototypes =======================================================================*/

long informUser(Hotlist_Data *data,char *format,BOOL window,ULONG flags,...);
long getString(Hotlist_Data *data,char *format,BOOL window,ULONG flags,\
				char *strbuff,long bufflen,...);
long getPathString(Hotlist_Data *data,char *format,BOOL window,ULONG flags,\
				char *strbuff,long bufflen,...);

BOOL getListerHandle(Hotlist_Data *data);
void sendExtCmd_nr(Hotlist_Data *data,char *cmdstring,struct command_packet *cpp);
void addEntries(Hotlist_Data *data,char *combuf,struct command_packet *cpp);
void mainEventLoop(Hotlist_Data *data,char *combuf,struct command_packet *cpp);
void writeConfigFile(Hotlist_Data *data);
void readConfigFile(Hotlist_Data *data,BOOL alreadylocked);
void splent(Hotlist_Data *data,BOOL alreadylocked,struct ClockData *newtime,char *msg);
void rereadConfig(Hotlist_Data *data,char *combuf,struct command_packet *cpp);
HotEntry *newHotEntry(Hotlist_Data *data);
void remHotEntry(Hotlist_Data *data);
void setHotType(Hotlist_Data *data,HotEntry *nhe);
void wordcpy(char *dest,char **source);
int wordcount(char *wordstring);
HotEntry *findHotEntry(Hotlist_Data *data,char *searchname);
BOOL findOldEntry(Hotlist_Data *data,char *searchname);
struct Window *getListerWindow(Hotlist_Data *data);
struct Screen *getDOpusScreen(Hotlist_Data *data);
void listerRead(Hotlist_Data *data,char *combuf,struct command_packet *cpp,char *path);

FuncArgs *parseArgs(Hotlist_Data *data,char *args);
void freeArgs(FuncArgs *fa);

void endcpy(char *dest,char *source,long destlen);
char *leofilepart(char *path);

LONG notHandled(Hotlist_Data *data,char *combuf,struct command_packet *cpp,char *lh);

BOOL addMsgPort(Hotlist_Data *data);
void remMsgPort(Hotlist_Data *data);

void basicListerInit(Hotlist_Data *data,char *combuf,struct command_packet *cpp);

BOOL event_inactive(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_doubleclick(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_dropfrom(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_drop(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_makedir(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_delete(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_path(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_scandir_hotlist(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_snapshot(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_unsnapshot(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_rename(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_parent(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);
BOOL event_duplicate(Hotlist_Data *data,char *combuf,struct command_packet *cpp,\
		char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6);

void getConfigSemaphore(Hotlist_Data *data,short obtype);
void getWriteConfigSemaphore(Hotlist_Data *data);

void notifyOn(Hotlist_Data *data);
void notifyOff(Hotlist_Data *data);

char *skipSpaces(char *text,int numspac);
