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

    MODUL
	smallspc.c

    DESCRIPTION
	minimal interface for special variables
	setting and reading

    NOTES
	look into future/...

    BUGS
	none known

    TODO
	entries for all new spcvars
	join the 3 functions into 1
	create a list that is scanned in a loop

    EXAMPLES

    SEE ALSO
	vars.c

    INDEX

    HISTORY
	21 Nov 92 null created
	28-07-94 null added "$version"

*!***************************************************************************
*!
*!  Special Variables - Overview
*!
*!  these are some builtin variables, which represent some
*!  more or less important things in XDME's interna
*!  since some of them are build via functions, not each of them
*!  is writable through the variable interface; however all of them
*!  should be readable via the variable interface
*!
*! this is the list of the currently supported Special variables
*!
*!	ascii
*!	autoindent
*!	autosplit
*!	autounblock
*!	activetofront
*!	bgpen
*!	bbpen
*!	colno
*!	currentline
*!	currentword
*!	cursorpen
*!	debug
*!	fgpen
*!	filename
*!	findstr
*!	fname
*!	fpath
*!	globalsearch
*!	hgpen
*!	ignorecase
*!	infixmode
*!	insertmode
*!	keytable
*!	lineno
*!	margin
*!	menustrip
*!	modified
*!	parcol
*!	qualifiers
*!	refpaths
*!	repstr
*!	restofline
*!	rexxport
*!	savetabs
*!	scanf
*!	tabstop
*!	textnames
*!	tpen
*!	viewmode
*!	wordwrap
*!	windowcycling
*!	version
*!
******************************************************************************/

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

/**************************************
	    Globale Variable
**************************************/
Prototype char* GetSpecialVar (char* Name);
Prototype char* GetSpecialInt (char* Name);
Prototype char* GetSpecialFlag(char* Name);

Prototype char SetSpecialFlag(char* Name, char* Value);
Prototype char SetSpecialInt (char* Name, char* Value);
Prototype char SetSpecialVar (char* Name, char* Value);

Prototype void do_togglespecialflag(void);
Prototype void do_setspecialvar(void);

extern UBYTE Fstr[];
extern UBYTE Rstr[];

/**************************************
      Interne Defines & Strukturen
**************************************/
    const char* N_ascii 	= "ascii";
    const char* N_autoindent	= "autoindent";
    const char* N_autosplit	= "autosplit";
    const char* N_autounblock	= "autounblock";
    const char* N_activetofront = "activetofront";
    const char* N_bgpen 	= "bgpen";
    const char* N_bbpen 	= "bbpen";
    const char* N_colno 	= "colno";
    const char* N_currentline	= "currentline";
    const char* N_currentword	= "currentword";
    const char* N_cursorpen	= "cursorpen";
    const char* N_debug 	= "debug";
    const char* N_fgpen 	= "fgpen";
    const char* N_filename	= "filename";
    const char* N_findstr	= "findstr";
    const char* N_fname 	= "fname";
    const char* N_fpath 	= "fpath";
    const char* N_globalsearch	= "globalsearch";
    const char* N_hgpen 	= "hgpen";
    const char* N_ignorecase	= "ignorecase";
    const char* N_infixmode	= "infixmode";
    const char* N_insertmode	= "insertmode";
    const char* N_keytable	= "keytable";
    const char* N_lineno	= "lineno";
    const char* N_margin	= "margin";
    const char* N_menustrip	= "menustrip";
    const char* N_modified	= "modified";
    const char* N_parcol	= "parcol";
    const char* N_qualifiers	= "qualifiers";
    const char* N_refpaths	= "refpaths";
    const char* N_repstr	= "repstr";
    const char* N_restofline	= "restofline";
    const char* N_rexxport	= "rexxport";
    const char* N_savetabs	= "savetabs";
    const char* N_scanf 	= "scanf";
    const char* N_tabstop	= "tabstop";
    const char* N_textnames	= "textnames";
    const char* N_tpen		= "tpen";
    const char* N_viewmode	= "viewmode";
    const char* N_wordwrap	= "wordwrap";
    const char* N_windowcycling = "windowcycling";
    const char* N_version	= "version";


/**************************************
	    Interne Variable
**************************************/


/**************************************
	   Interne Prototypes
**************************************/
Prototype char* current_word (void);


/*
**  GetSpecialVar - Get one of the internal special String Vars:
**
**  >name == the name of the variable to search for
**  <ptr to malloced string
**  <NULL == not found or error
*/

char*
GetSpecialVar(char* Name)
{
    int i,j;
    char* str;		/* return */
    char* ptr;		/* help: if not NULL, anything was found */

    str = NULL;
    ptr = NULL;
    i = 0;
    j = 0;
/* printf("Vn=%s\n",Name); */

    if ((Name == NULL) || (Name[0] == 0))
    {
	return(NULL);
    } /* if */
					/* String Variables */

    switch (Name[0])
    {
    case 'c':
	if (strcmp (Name, N_currentline) == 0)
	{ /* old */
	    ptr = Current;
	} else
	if (strcmp (Name, N_currentword) == 0)
	{ /* new */
	    ptr = current_word();
	} /* if */
	break;
    case 'f':
	if (strcmp (Name, N_filename) == 0)
	{    /* old */
	    ptr = Ep->name;
	} else
	if (strcmp (Name, N_fname) == 0)
	{	/* old */
	    ptr = fname(Ep->name);
	} else
	if (strcmp (Name, N_findstr) == 0)
	{     /* old */
	    ptr = Fstr;
	} /* if */
	break;

    case 'k':                                   /* PATCH_NULL [01 Feb 1993] : added */
	if (strcmp (Name, N_keytable) == 0)
	{
	    if (ptr = currenthash()) {
		ptr = ((struct Node *)ptr)->ln_Name;
	    } /* if */
	} /* if */
	break;
    case 'm':                                   /* PATCH_NULL [01 Feb 1993] : added */
	if (strcmp (Name, N_menustrip) == 0)
	{
	    if (ptr = currentmenu()) {
		ptr = ((struct Node *)ptr)->ln_Name;
	    } /* if */
	} /* if */
	break;
    case 'r':
	if (strcmp (Name, N_repstr) == 0)
	{      /* old */
	    ptr = Rstr;
	} else
	if (strcmp (Name, N_restofline) == 0)
	{
	    if (Clen>=Ep->column) {
		ptr = Current + Ep->column;	    /* DANGER */
	    } else {
		ptr = Current + Clen;
	    } /* if */
	} /* if */
	break;
    case 's':
	if (strcmp (Name, N_scanf) == 0)
	{	/* old */
	    ptr = String;
	} /* if */
	break;
    case 'v':
	if (strcmp (Name, N_version) == 0)
	{	/* old */
	    ptr = version;
	} /* if */
	break;

    default:
	break;
    } /* switch */

    if (ptr != NULL)
    {
	str = malloc (strlen(ptr)+1);
	if (str)
	{
	    strcpy(str, ptr);
	    return(str);
	} else if (*ptr != 0)
	{
	    nomemory();
	    abort(NULL);
	} else
	{
	    return(str);
	} /* if */
    } /* if */

    return(NULL);
} /* GetSpcVar */


/*
**  SetSpecialVar - set one of DME's internal special String vars
**
**  >Name  - name of the variable to modify
**  >Value - new value of the variable
**  <0 == name not found
**  <1 == ok ( also if variable is readonly )
*/

char
SetSpecialVar(char* Name, char* Value)
{
    char* ptr;
    int len;

    if ((Name == NULL) || (Name[0] == 0))
    {
	return(0);
    } /* if */
    ptr = NULL;
    len = LINE_LENGTH;

/* printf("Vs=%s\n",Name); */

	if (strcmp (Name, N_filename) == 0)
	{
	    ptr = Ep->name;
	    len = 63;
	} else

	if (strcmp (Name, N_findstr) == 0)
	{
	    ptr = Fstr;
	} else
	if (strcmp (Name, N_repstr) == 0)
	{
	    ptr = Rstr;
	} else
	if (strcmp (Name, N_scanf) == 0)
	{
	    ptr = String;
	} else
	if (strcmp (Name, N_currentline) == 0)
	{
	    abort(1);
	} else
	if (strcmp (Name, N_currentword) == 0)
	{
	    abort(1);
	} else
	if (strcmp (Name, N_version) == 0)
	{
	    abort(1);
	} else
	if (strcmp (Name, N_restofline) == 0)
	{
	    abort(1);
	} /* if */

    if (ptr)
    {
	strncpy(ptr, Value, len);
	return(1);  /* found */
    } else
	return(0);  /* not found */
} /* SetSpecialVar */



/*
**  GetSpecialInt - Get one of the internal special Integer Vars:
**
**  >name == the name of the variable to search for
**  <ptr to malloced string
**  <NULL == not found or error
*/

char*
GetSpecialInt(char* Name)
{
    int found;
    long i;
    char* str;		/* return */
    char buffer[16];	/* help: convert numbers here */

    found = 0;
/* printf("In=%s\n",Name); */

	if (strcmp (Name, N_ascii) == 0)
	{ /* current char */
	    i = Current[Ep->column];
	    found = 1;
	} else
	if (strcmp (Name, N_bbpen) == 0)
	{ /* highlight pen */
	    i = BLOCK_BPEN;
	    found = 1;
	} else
	if (strcmp (Name, N_bgpen) == 0)
	{ /* background pen */
	    i = TEXT_BPEN;
	    found = 1;
	} else
	if (strcmp (Name, N_colno) == 0)
	{ /* current xpos */
	    i = Ep->column + 1;
	    found = 1;
	} else
	if (strcmp (Name, N_fgpen) == 0)
	{ /* foreground pen */
	    i = TEXT_FPEN;
	    found = 1;
	} else
	if (strcmp (Name, N_hgpen) == 0)
	{ /* highlight pen */
	    i = BLOCK_FPEN;
	    found = 1;
	} else
	if (strcmp (Name, N_lineno) == 0)
	{ /* current ypos */
	    i =  Ep->line + 1;
	    found = 1;
	} else
	if (strcmp (Name, N_margin) == 0)
	{ /* right margin for wordwrap */
	    i = Ep->config.margin;
	    found = 1;
	} else
	if (strcmp (Name, N_parcol) == 0)
	{ /* left margin of paragraph? */
	    i = Ep->config.wwcol;
	    found = 1;
	} else
	if (strcmp (Name, N_tpen) == 0)
	{ /* title bar rendering */
	    i = TITLE_BPEN;
	    found = 1;
	} else
	if (strcmp (Name, N_tabstop) == 0)
	{
	    i = Ep->config.tabstop;
	    found = 1;
	} /* if */


    if (found)
    {
	sprintf(buffer,"%ld",i);
	str = malloc(strlen(buffer)+1);
	if (str)
	{
	    strcpy(str, buffer);
	    return(str);
	} else
	{
	    nomemory();
	    abort(NULL);
	} /* if */
    } /* if */
    return(NULL);
} /* GetSpecialInt */



/*
 *  GetSpecialFlag - Get one of the internal special Flags:
 *
 *  >name == the name of the variable to search for
 *  <ptr to malloced string
 *  <NULL == not found or error
 */

char*
GetSpecialFlag(char* Name)
{
    char i,found;
    char* str;		/* return */
    char buffer[4];	/* help: convert numbers here */

/* printf("Fn=%s\n",Name); */
    found = 0;
							/* locals */
	if (strcmp (Name, N_autounblock) == 0)
	{
	    i = Ep->config.autounblock ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_autoindent) == 0)
	{
	    i = Ep->config.autoindent ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_autosplit) == 0)
	{
	    i = Ep->config.autosplit ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_debug) == 0)
	{
	    i = globalflags.debug ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_infixmode) == 0)
	{  /* while searching */
	    i = Ep->config.ignorecase ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_insertmode) == 0)
	{  /* <-> overwrite */
	    i = Ep->config.insertmode ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_modified) == 0)
	{    /*  */
	    i = Ep->modified ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_viewmode) == 0)
	{
	    i = Ep->viewmode ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_wordwrap) == 0)
	{
	    i = Ep->config.wordwrap ? 1 : 0;
	    found = 1;
	} else

						    /* globals */
	if (strcmp (Name, N_activetofront) == 0)
	{
	    i = globalflags.ActivateToFront ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_globalsearch) == 0)
	{
	    i = globalflags.global_search ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_infixmode) == 0)
	{   /* <-> prefixmode / math2 */
	    i = MathInfix ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_savetabs) == 0)
	{
	    i = globalflags.Savetabs ? 1 : 0;
	    found = 1;
	} else
	if (strcmp (Name, N_windowcycling) == 0)
	{
	    i = globalflags.Windowcycling ? 1 : 0;
	    found = 1;
	/* aborted */
	} /* if */

    if (found)
    {
	sprintf(buffer,"%ld",i);
	if (str = strdup(buffer))
	{
	    return(str);
	} else
	{
	    nomemory();
	    abort(NULL);
	} /* if */
    } /* if */
    return(NULL);
} /* GetSpecialFlag */



/*
 *  SetSpecialInt - Set a special Integer variable
 *
 *  >Name  - name of the variable to modify
 *  >value - new value of the variable
 *  <0 == name not found or value was no integer
 *  <1 == name found (also if variable is write only)
 */

char
SetSpecialInt(char* name, char* value)
{
    int   val;
//    char found = 0;

/* printf("Is=%s\n",name); */
    if (!is_number(value))
    {  /* --- that is not correct but easy */
	return(0);
    } /* if */
    val = atoi(value);


	if ((strcmp (name, N_bgpen) == 0) ||
	  (strcmp (name, N_colno) == 0) ||
	  (strcmp (name, N_lineno) == 0) ||
	  (strcmp (name, N_fgpen) == 0) ||
	  (strcmp (name, N_hgpen) == 0) ||
	  (strcmp (name, N_tpen) == 0))
	  {
	    abort(1);
	} else
	if (strcmp (name, N_ascii) == 0)
	{
	    if (!Ep->viewmode)
	    {
		Current[Ep->column] = val / LINE_LENGTH;
	    } /* if */
	} else
	if (strcmp (name, N_margin) == 0)
	{
	    Ep->config.margin = val % (LINE_LENGTH);
	} else
	if (strcmp (name, N_parcol) == 0)
	{
	    Ep->config.wwcol = val % (LINE_LENGTH);
	} else
	if (strcmp (name, N_tabstop) == 0)
	{
	    Ep->config.tabstop = val % (LINE_LENGTH);
	} else
	{
	    return(0);  /* not found */
	} /* if */
    return(1);      /* found */
} /* SetSpecialInt */



/*
 *  SetSpecialFlag - Set a specialFlag
 *
 *  >Name  - name of the variable to modify
 *  >value - new value of the variable
 *  <0 == name not found
 *  <1 == ok ( also if other error)
 */

char
SetSpecialFlag(char* name, char* value)
{
    char* charptr;
    char* comment;
    char  buffer[32];
    char* com[2];

    charptr = NULL;
    comment = NULL;
    com[0]  = "Off";
    com[1]  = "On";

#define ChangeBitFlag(name,comment)                                 \
    {								    \
	Ep->config. name = test_arg (value, Ep->config. name );     \
	sprintf(buffer,"%s %s ", comment, com[Ep->config. name ]);  \
	title(buffer);                                              \
	return(1);                                                  \
    }

    /* printf("Fs=%s\n",name); */
    /* --- local flags */

    if (strcmp (name, N_autounblock) == 0)
	ChangeBitFlag(autounblock,"Autounblock")
    else if (strcmp (name, N_autoindent) == 0)
	ChangeBitFlag(autoindent,"Autoindent")
    else if (strcmp (name, N_autosplit) == 0)
	ChangeBitFlag(autosplit,"Autosplit")
    else if (strcmp (name, N_ignorecase) == 0)
    {	/* search case <-> ignorecase */
	com[0]	= "Sensitive";
	com[1]	= "InSensitive";
	ChangeBitFlag(ignorecase,"Case")
    }
    else if (strcmp (name, N_insertmode) == 0)
	/* <-> overwrite text */
	ChangeBitFlag(insertmode,"Inset Mode")
    else if (strcmp (name, N_wordwrap) == 0)
	ChangeBitFlag(wordwrap,"Wordwrap")

    /* editor-specific flags */
#undef ChangeBitFlag
#define ChangeBitFlag(name,comment)                                 \
    {								    \
	Ep-> name = test_arg (value, Ep-> name);                    \
	sprintf(buffer,"%s %s ",comment, com[Ep-> name]);           \
	title(buffer);                                              \
	return(1);                                                  \
    }

    else if (strcmp (name, N_viewmode) == 0)
	ChangeBitFlag(viewmode,"Viewmode")
    else if (strcmp (name, N_modified) == 0)
	ChangeBitFlag(modified,"Modified")

    /* --- global flags */
#undef ChangeBitFlag
#define ChangeBitFlag(name,comment)                                 \
    {								    \
	globalflags.name = test_arg (value, globalflags.name);      \
	sprintf(buffer,"%s %s ",comment, com[globalflags.name]);     \
	title(buffer);                                              \
	return(1);                                                  \
    }

    else if (strcmp (name, N_activetofront) == 0)
	ChangeBitFlag(ActivateToFront,"Moving Activated Windows To Front")
    else if (strcmp (name, N_debug) == 0)
	ChangeBitFlag(debug,"Debugging mode")
    else if (strcmp (name, N_globalsearch) == 0)
	ChangeBitFlag(global_search,"Global Searching")
    else if (strcmp (name, N_savetabs) == 0)
	/* save tabs or whitespaces */
	ChangeBitFlag(Savetabs,"Save tabs")
    else if (strcmp (name, N_windowcycling) == 0)
	ChangeBitFlag(Windowcycling,"Windowcycling")

#undef ChangeBitFlag

    return(0);     /* not found */
} /* SetSpecialFlag */



/*
 *	This function is to be called for all toggling any special flag
 *	via a command:	    flagname mode
 *  The only thing is - the variable must be treated here
 */

void
do_togglespecialflag()
{
    if (!SetSpecialFlag(av[0],av[1]))
	abort2();
} /* do_togglespecialflag */



/*
 *	This function might be called for all setting any special var
 *	via a command:	    varname mode
 *  The only thing is - the variable must be treated here
 */

void
do_setspecialvar()
{
    if ( !SetSpecialInt(av[0],av[1])
      && !SetSpecialVar(av[0],av[1]) )
	abort2();
} /* do_setspecialvar */


/*
**  Redefine these names to adjust the used buffers to Your settings
**  the commands are 'atomic' so there should be no interference to
**  other 'atomic' commands using them.
**
**  for XDME changed buffers[0]/buffers[1] to tmp_buffer/tmp_buf2
*/
#define firstbuffer  tmp_buffer




/*
* !  $[SPC.]currentword
* !	 that read-only special-variable
* !	 represents "the word under the cursor"
* !	 that means it finds the beginning of the current word on
* !	 on its own (but we do not move the cursor) if cursor is
* !	 not within a word, it returns the next word of the line
* !	 if there is no next word, an empty string is returned
* !  NOTE this variable is not accessible, if PATCH_VARS is not active
* !
**  current_word		   (uses firstbuffer)
**
**  Returns the word under the cursor,
**  is used by fastscan and should be used by ref and tag instead of
**  their own functions
*/

#define isC(ch)     (isalnum((ch)) || (ch) == '_')

char * current_word (void)
{
    register char * str;
    register int i,j;

    str = (char *)firstbuffer;

    i = Ep->column;
    while ((i>0) && isC(Current[i]))
    {	       /*  goto beginning of word */
	i--;
    } /* while */
    while ((Current[i]) && !isC(Current[i]))
    {  /* skip spaces and other garbage */
	i++;
    } /* while */

    j = 0;
    while (isC(Current[i]) && (j <= LINE_LENGTH))
    {
	str[j] = Current[i];				/* copy "word" into buffer */
	j++;
	i++;
    } /* while */
    str[j] = 0;

    return (str);
} /* current_word */


/******************************************************************************
*****  ENDE smallspc.c
******************************************************************************/
