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

    MODUL
	lowlevelmacros.c

    DESCRIPTION
	die schnittstelle zu den wichtigsten Macro-funktionen,
	die von anderen Moduln verwendet werden duerfen.

    NOTES
	dies ist nur ein Dummy - Modul, das zwar alle
	Funktionen exportiert, die beschrieben wurden,
	ihre Realisierung ist jedoch stark eingeschraenkt,
	sie sind auf einfache Strings zurueckgeschraubt,
	so dass die sie verwendenden Moduln wie vorher
	angesprochen werden koennen.

    BUGS

    TODO
	bei Gelegenheit sollte dieses Modul komplett neu geschrieben werden
	und mit alias.c und main.c neu abgestimmt werden
	(so dass main.c callmacro verwendet neque vero do_command)

    EXAMPLES

    SEE ALSO

    INDEX

    HISTORY

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

/**************************************
		Includes
**************************************/
#include "defs.h"


/**************************************
	    Globale Variable
**************************************/
Prototype UBYTE * GetArg      (int);
Prototype UBYTE * CommandName (void);


Prototype void clear_record	(void);
Prototype void start_recording	(void);
Prototype void end_recording	(void);
Prototype void replay_record	(void);
Prototype void do_saverecord	(void);
Prototype void add_record	(char * string);


/**************************************
      Interne Defines & Strukturen
**************************************/


/**************************************
	    Interne Variable
**************************************/
static char tempmacro_buffer[LINE_LENGTH];


/**************************************
	   Interne Prototypes
**************************************/


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

		Dies ist lediglich eine Uebergangsloesung,
		solange wir alias.c und main.c noch nicht
		umgeschrieben haben

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




UBYTE * CommandName (void)
{
    return (av[0]);
} /* CommandName */

UBYTE * GetArg (int num)
{
    return(av[num]);
} /* GetArg */




/*
**  MACRO RECORDER
**	we can record one input - sequence and replay it
**
**	there are 3 functions:
**
**  recording
**	int Start_recording (void)
**	int add_record	    (char * string)
**	int end_recording   (void)
**
**  playing
**	int replay_record   (void)
**
**  saving
**	int save_record     (FILE * fo)
**	    (can be sourced)
**
*/

static struct MinList record =	/* list to contain the macros */
{
    (struct MinNode *)&record.mlh_Tail, NULL,
    (struct MinNode *)&record.mlh_Head
};
static WORD	      record_replaying	 = 0;			  /* security to avoid endless loops */

struct LongNode {
    struct MinNode node;
    char	   com[0];
};

void clear_record (void)
{
    struct LongNode * ln;

    while (ln = (struct LongNode *)RemHead ((struct List *)&record)) {
	FreeMem (ln, sizeof (struct MinNode) + 1 + strlen (ln->com));
    } /* while */
} /* clear_record */

void start_recording (void)
{
    if (!record_replaying) {
	if (MacroRecord == 0) {
	    clear_record();
	} /* if */

	MacroRecord ++;
    } else {
	error ("%s:\nYou can NOT start recording,\nwhile You are replaying a record", av[0]);
    } /* if */
} /* start_recording */

void end_recording (void)
{
    if (MacroRecord) {
	MacroRecord --;

	{
	    char ab = globalflags.Abortcommand;
	    error ("recorder ended!");
	    globalflags.Abortcommand = ab;
	}

#	ifdef NOT_DEF
	    /* strenggenommen muessten wir zuallererstden recorderend aus dem letzten string herausfiltern */
	    /* was aber, wenn der nicht als command sondern als macro kam ??? */
	    if (MacroRecord == ~0) {
		struct LongNode * ln;
		if (ln = (struct LongNode *)RemTail ((struct List *)&record)) {
		    strcpy (tmp_buffer, ln->com);

		} /* if */
	    } /* if */
#	endif
 /* } else if (!record_replaying) { */
     /* error ("%s:\nYou can NOT end recording,\nif You are NOT recording", av[0]); */
    } /* if */
} /* end_recording */

void add_record (char * string)
{
    if (!record_replaying) {
	struct LongNode * ln;

	if (ln = AllocMem (sizeof (struct MinNode) + 1 + strlen (string), MEMF_ANY)) {
	    strcpy (ln->com, string);
	    AddTail ((struct List *)&record, (struct Node *)ln);
	} else {
	    nomemory ();     /* do NOT abort - we have to execute commands, too */
	} /* if */

	if (breakcheck()) {  /* that way we might have a sure record-terminator - the CTL-C signal */
	    end_recording ();
	} /* if */
    } /* if */
} /* add_record */

void replay_record (void)
{
    if (!record_replaying) {
	if (GetHead (&record)) {
	    char * buffer;
	    /* We use a run-time allocated buffer */
	    if (!(buffer = AllocMem (LINE_LENGTH, MEMF_ANY))) {
		nomemory ();     /* error() NEEDS memory for itself */
		globalflags.Abortcommand = 1;
		return;
	    } else {
		struct LongNode * ln;

		for (ln = GetHead (&record); ln; ln = GetSucc (ln)) {
		    strncpy (buffer, ln->com, LINE_LENGTH-1);
		    do_command (buffer);

		    /* You can NOT terminate Your record by errors */
		    clearbreaks ();

		    /* You can break Your record by pressing Ctrl-C */
		    if (breakcheck ()) {
			globalflags.Abortcommand = 1;
			break;
		    } /* if */
		} /* for */

		FreeMem (buffer, LINE_LENGTH);
	    } /* if alloced */
	} /* if */
    } else {
	error ("%s:\nYou can NOT start replaying a record,\nwhile You are already replaying it", av[0]);
    } /* if not already replaying */
} /* replay_record */

void save_record (FILE * fo)
{
    if (fo) {
	struct LongNode * ln;
	for (ln = GetHead (&record); ln; ln = GetSucc (ln)) {
	    sprintf (tmp_buffer, "%s\n", ln->com);
	    if (fputs (tmp_buffer, fo) < 0) {
		error ("%s:\nError while writing the\ncurrent record!", av[0]);
		break;
	    } /* if */
	} /* for */
    } /* if */
} /* save_record */

void do_saverecord (void)
{
    FILE  * fo;

    if (!GetHead (&record)) {
	error ("%s:\nCan not save a record,\n if there is NO record!", av[0]);
    } else {
	if (fo = fopen (av[1], "w")) {
	    save_record (fo);
	    fclose (fo);
	} else {
	    error ("%s:\n Can not open File\n'%s' for output", av[0], av[1]);
	} /* if */
    } /* if */
} /* do_saverecord */





/******************************************************************************
*****  ENDE macros.c
******************************************************************************/
