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

    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

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

/**************************************
		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";


/**************************************
	    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;
    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_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";

/* printf("Fs=%s\n",name); */
/* --- local flags */
	if (strcmp (name, N_autounblock) == 0)
	{
	    charptr = &Ep->config.autounblock;
	    comment = "Autounblock";
	} else
	if (strcmp (name, N_autoindent) == 0)
	{
	    charptr = &Ep->config.autoindent;
	    comment = "Autoindent";
	} else
	if (strcmp (name, N_autosplit) == 0)
	{
	    charptr = &Ep->config.autosplit;
	    comment = "Autosplit";
	} else
	if (strcmp (name, N_ignorecase) == 0)
	{   /* search case <-> ignorecase */
	    charptr = &Ep->config.ignorecase;
	    comment = "Case";
	    com[0]  = "Sensitive";
	    com[1]  = "InSensitive";
	} else
	if (strcmp (name, N_insertmode) == 0)
	{   /* <-> overwrite text */
	    charptr = &Ep->config.insertmode;
	    comment = "Insert mode";
	} else
	if (strcmp (name, N_wordwrap) == 0)
	{
	    charptr = &Ep->config.wordwrap;
	    comment = "WordWrap";
#ifdef NOTDEF
	} else
	if (strcmp (name, N_viewmode) == 0)
	{
	    charptr = &Ep->viewmode;
	    comment = "Viewmode";
	} else
	if (strcmp (name, N_modified) == 0)
	{     /* text-modified */
	    charptr = &Ep->modified;
	    comment = "Modified";
#endif
	}

#ifdef NOTDEF
/* --- global flags */
	else if (strcmp (name, N_activetofront) == 0)
	{
	    charptr = &globalflags.ActivateToFront;
	    comment = "Moving Activated Windows To Front";
	} else
	if (strcmp (name, N_debug) == 0)
	{
	    charptr = &globalflags.debug;
	    comment = "Debugging mode";
	} else
	if (strcmp (name, N_globalsearch) == 0)
	{
	    charptr = &globalflags.global_search;
	    comment = "Global Searching";
	} else
	if (strcmp (name, N_infixmode) == 0)
	{    /* math infixmode <-> prefixmode */
	    charptr = &globalflags.MathInfix;
	    comment = "Infixmode";
	} else
	if (strcmp (name, N_savetabs) == 0)
	{     /* save tabs or whitespaces */
	    charptr = &globalflags.Savetabs;
	    comment = "SaveTabs";
	} else
	if (strcmp (name, N_windowcycling) == 0)
	{
	    charptr = &globalflags.Windowcycling;
	    comment = "Windowcycling";
	} /* if */
#endif

    if (charptr)
    {
	*charptr = test_arg (value, *charptr);
	if (comment)
	{
	    sprintf(buffer,"%s %s ",comment, com[*charptr]);
	    title(buffer);
	} /* if */
	return(1); /* found */
    } /* if */
    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]))
	abort();
} /* 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]) )
	abort();
} /* 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 = 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
******************************************************************************/
