
/*
 * PREFS.C
 * (c) 1992-3 J.Harper
 */

#include "jed.h"
#include "revision.h"
#include "jed_protos.h"

#define PREFFILE "s:jed.config"

Prototype   VOID    copyprefs	    (VW *, VW *);
Local	    VOID    cloneprefs	    (TX *, VW *);
Prototype   VOID    getdefprefs	    (TX *);
Local	    BOOL    interpretprefs  (STRPTR, TX *);
Prototype   BOOL    setupfileprefs  (TX *);
Prototype   BOOL    savefileprefs   (TX *);
Prototype   VALUE * cmd_saveprefs   (LONG, VALUE *);
Prototype   VALUE * cmd_setpref	    (LONG, VALUE *);
Prototype   VALUE * cmd_getpref	    (LONG, VALUE *);
Prototype   VALUE * cmd_info	    (LONG, VALUE *);
Prototype   VOID    setdefprefs	    (VW *);

const UBYTE ConfigFileTxt[] = PREFFILE;
STRPTR	    ConfigFile	    = ConfigFileTxt;
LONG	    ConfigVersion   = 7;

Prototype PREFS DefPrefs;
Prototype WORD	DefDims[4];
Prototype BOOL	SaveFilePrefs;
Prototype BOOL	ScrollHack;

__config  PREFS DefPrefs =
{
    FALSE,
    FALSE,
    FALSE,
    8,
    8,
    FALSE,
    0,
    77,
    "topaz.font",
    8,
    "t:",
    2,
    ""
};
__config  WORD	DefDims[4] = { 0, 0, 640, 200 };
__config  BOOL	SaveFilePrefs = FALSE;
__config  BOOL	ScrollHack = TRUE;

VOID
copyprefs(VW *dest, VW *src)
{
    if(src)
	memcpy(&dest->vw_Prefs, &src->vw_Prefs, sizeof(PREFS));
    else
	memcpy(&dest->vw_Prefs, &DefPrefs, sizeof(PREFS));
}

/*
 * Copies PREFS from one view to all other views of the same file
 * _doesn't_ copy font
 */
Local VOID
cloneprefs(TX *tx, VW *src)
{
    VW *thisvw;
    for(thisvw = (VW *)tx->tx_Views.mlh_Head; thisvw->vw_Node.mln_Succ; thisvw = (VW *)thisvw->vw_Node.mln_Succ)
    {
	if(thisvw != src)
	{
	    PREFS *srcp = &src->vw_Prefs;
	    PREFS *dstp = &thisvw->vw_Prefs;
	    dstp->prf_WordWrap = srcp->prf_WordWrap;
	    dstp->prf_AutoIndent = srcp->prf_AutoIndent;
	    dstp->prf_TabSize = srcp->prf_TabSize;
	    dstp->prf_DiskTab = srcp->prf_DiskTab;
	    dstp->prf_SaveTabs = srcp->prf_SaveTabs;
	    dstp->prf_LeftMargin = srcp->prf_LeftMargin;
	    strcpy(dstp->prf_BakDir, srcp->prf_BakDir);
	    dstp->prf_MaxBak = srcp->prf_MaxBak;
	    strcpy(dstp->prf_ScreenName, srcp->prf_ScreenName);
	}
    }
}

VOID
getdefprefs(TX *dst)
{
    VW *thisvw;
    dst->tx_ResetPrefs = FALSE;
    for(thisvw = (VW *)dst->tx_Views.mlh_Head; thisvw->vw_Node.mln_Succ; thisvw = (VW *)thisvw->vw_Node.mln_Succ)
    {
	PREFS *srcp = &DefPrefs;
	PREFS *dstp = &thisvw->vw_Prefs;
	dstp->prf_WordWrap = srcp->prf_WordWrap;
	dstp->prf_AutoIndent = srcp->prf_AutoIndent;
	dstp->prf_TabSize = srcp->prf_TabSize;
	dstp->prf_DiskTab = srcp->prf_DiskTab;
	dstp->prf_SaveTabs = srcp->prf_SaveTabs;
	dstp->prf_LeftMargin = srcp->prf_LeftMargin;
	strcpy(dstp->prf_BakDir, srcp->prf_BakDir);
	dstp->prf_MaxBak = srcp->prf_MaxBak;
	strcpy(dstp->prf_ScreenName, srcp->prf_ScreenName);
    }
}

/*
 * sets preferences from a string in the format,
 * @@ww<+|->\ai<+|->\tsN\dtN\stN\lmN\rmN
 * ie,
 * @@ww-\ai+\ts4\dt8\st2\lm0\rm77
 */
Local BOOL
interpretprefs(STRPTR str, TX *tx)
{
    BOOL rc = TRUE;
    if((str[0] == '@') && (str[1] == '@'))
    {
	VW *vw = (VW *)tx->tx_Views.mlh_Head;
	setdefprefs(vw);
	str += 2;
	while(*str && rc)
	{
	    UWORD opt;
	    opt = (str[0] << 8) | str[1];
	    str += 2;
	    switch(opt)
	    {
		case 'ww':
		    vw->vw_Prefs.prf_WordWrap = (*str == '+') ? TRUE : FALSE;
		    str++;
		    break;
		case 'ai':
		    vw->vw_Prefs.prf_AutoIndent = (*str == '+') ? TRUE : FALSE;
		    str++;
		    break;
		case 'ts':
		    WORD ts = strtol(str, &str, 0);
		    if(ts)
			vw->vw_Prefs.prf_TabSize = ts;
		    else
			settitle("error: tabsize must be >0");
		    break;
		case 'dt':
		    WORD dt = strtol(str, &str, 0);
		    if(dt)
			vw->vw_Prefs.prf_DiskTab = dt;
		    else
			settitle("error: disktab must be >0");
		    break;
		case 'st':
		    vw->vw_Prefs.prf_SaveTabs = strtol(str, &str, 0);
		    break;
		case 'lm':
		    vw->vw_Prefs.prf_LeftMargin = strtol(str, &str, 0);
		    break;
		case 'rm':
		    vw->vw_Prefs.prf_RightMargin = strtol(str, &str, 0);
		    break;
		default:
		    settitle("error: unknown embedded preference");
		    rc = FALSE;
		    break;
	    }
	    if(*str == '\\')
		str++;
	    else
		str = str + strlen(str);
	}
	tx->tx_ResetPrefs = TRUE;
	cloneprefs(tx, vw);
    }
    return(rc);
}

BOOL
setupfileprefs(TX *tx)
{
    BPTR lock;
    BOOL rc = FALSE;
    if(tx->tx_ResetPrefs)
	getdefprefs(tx);
    if(lock = Lock(tx->tx_FileName, SHARED_LOCK))
    {
	__aligned struct FileInfoBlock fib;
	if(Examine(lock, &fib))
	    rc = interpretprefs(fib.fib_Comment, tx);
	UnLock(lock);
    }
    return(rc);
}

BOOL
savefileprefs(TX *tx)
{
    BOOL rc = FALSE;
    if(SaveFilePrefs)
    {
	BPTR lock = Lock(tx->tx_FileName, SHARED_LOCK);
	if(lock)
	{
	    __aligned struct FileInfoBlock fib;
	    if(Examine(lock, &fib))
	    {
		STRPTR cmt = fib.fib_Comment;
		if((!cmt[0]) || ((cmt[0] == '@') && (cmt[1] == '@')))
		{
		    VW *vw = (VW *)tx->tx_Views.mlh_Head;
		    sprintf(cmt, "@@ww%lc\\ai%lc\\ts%ld\\dt%ld\\st%ld\\lm%ld\\rm%ld",
			vw->vw_Prefs.prf_WordWrap ? '+' : '-',
			vw->vw_Prefs.prf_AutoIndent ? '+' : '-',
			vw->vw_Prefs.prf_TabSize,
			vw->vw_Prefs.prf_DiskTab,
			vw->vw_Prefs.prf_SaveTabs,
			vw->vw_Prefs.prf_LeftMargin,
			vw->vw_Prefs.prf_RightMargin);
		    rc = SetComment(tx->tx_FileName, cmt);
		}
	    }
	    UnLock(lock);
	}
    }
    else
	rc = TRUE;
    return(rc);
}

VOID
setdefprefs(VW *src)
{
    if(!src->vw_Tx->tx_ResetPrefs)
	memcpy(&DefPrefs, &src->vw_Prefs, sizeof(PREFS));

    if(!src->vw_Prefs.prf_NoSnapshotWin)
	memcpy(DefDims, src->vw_Sleeping ? src->vw_OldDimensions : &src->vw_Window->LeftEdge, 2*4);
}

/*
 * defines whether or not config file will be saved on exit
 * returns *previous* status.
 */
VALUE *
cmd_saveprefs(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_NUMBER))
    {
	setnumres(ConfigFile ? TRUE : FALSE);
	ConfigFile = ARG1.val_Value.Number ? ConfigFileTxt : NULL;
    }
    return(&RES);
}

/*
 * (setpref `font' `name.font' size)
 * (setpref `wordwrap' bool)
 * (setpref `autoindent' bool)
 * (setpref `tabsize' size)
 * (setpref `leftmargin' col)
 * (setpref `rightmargin' col)
 * (setpref `disktab' size)
 * (setpref `savetabs' code)    0=none,1=leading,2=all
 * (setpref `scrollhack' bool)
 * (setpref `saveprefs' bool)
 * (setpref `reset' bool)       ; undocumented!
 * (setpref `nosnapshot' bool)
 * (setpref `pubscreen' name)
 */
VALUE *
cmd_setpref(LONG argc, VALUE *argv)
{
    WORD rc = -1;
    if(ARG1.val_Type == VTF_STRING)
    {
	VW *vw = CurrVW;
	switch(tolower(*(ARG1.val_Value.String)))
	{
	    case 'a':   /* autoindent */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    vw->vw_Prefs.prf_AutoIndent = ARG2.val_Value.Number;
		    rc = TRUE;
		}
		break;
	    case 'd':   /* disktab */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    vw->vw_Prefs.prf_DiskTab = ARG2.val_Value.Number;
		    rc = TRUE;
		}
		break;
	    case 'f':   /* font */
		if((ARG2.val_Type == VTF_STRING) && (ARG3.val_Type == VTF_NUMBER))
		{
		    UBYTE oldfont[30];
		    LONG oldsize = vw->vw_Prefs.prf_FontSize;
		    strncpy(vw->vw_Prefs.prf_FontName, oldfont, 30);
		    vw->vw_Prefs.prf_FontSize = ARG3.val_Value.Number;
		    strncpy(vw->vw_Prefs.prf_FontName, ARG2.val_Value.String, 30);
		    if(setfont(vw))
		    {
			vw->vw_RefreshType |= RFF_ALL;
			resyncxy();
			rc = TRUE;
		    }
		    else
		    {
			settitle("error: can't open font");
			strncpy(vw->vw_Prefs.prf_FontName, oldfont, 30);
			vw->vw_Prefs.prf_FontSize = oldsize;
			rc = FALSE;
		    }
		}
		break;
	    case 'l':   /* leftmargin */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    vw->vw_Prefs.prf_LeftMargin = ARG2.val_Value.Number - 1;
		    rc = TRUE;
		}
		break;
	    case 'r':   /* rightmargin | reset */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    if(!strcmp(ARG1.val_Value.String, "reset"))
			vw->vw_Tx->tx_ResetPrefs = (BOOL)(ARG2.val_Value.Number);
		    else
			vw->vw_Prefs.prf_RightMargin = ARG2.val_Value.Number - 1;
		    rc = TRUE;
		}
		break;
	    case 't':   /* tabsize */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    vw->vw_Prefs.prf_TabSize = ARG2.val_Value.Number;
		    rc = TRUE;
		}
		break;
	    case 'w':   /* wordwrap */
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    vw->vw_Prefs.prf_WordWrap = ARG2.val_Value.Number;
		    rc = TRUE;
		}
		break;
	    case 's':   /* savetabs | scrollhack */
		if(!strcmp(ARG1.val_Value.String, "saveprefs"))
		{
		    SaveFilePrefs = ARG2.val_Value.Number;
		    rc = TRUE;
		}
		else if(ARG1.val_Value.String[1] != 'c')
		{
		    if(ARG2.val_Type == VTF_NUMBER)
		    {
			vw->vw_Prefs.prf_SaveTabs = ARG2.val_Value.Number;
			rc = TRUE;
		    }
		}
		else
		{
		    if(ARG2.val_Type == VTF_NUMBER)
		    {
			ScrollHack = ARG2.val_Value.Number;
			rc = TRUE;
		    }
		}
		break;
	    case 'b':
		if(!stricmp(ARG1.val_Value.String, "bakdir"))
		{
		    if(ARG2.val_Type == VTF_STRING)
		    {
			strncpy(vw->vw_Prefs.prf_BakDir, ARG2.val_Value.String, 99);
			rc = TRUE;
		    }
		}
		else
		{
		    if(ARG2.val_Type == VTF_NUMBER)
		    {
			vw->vw_Prefs.prf_MaxBak = ARG2.val_Value.Number;
			rc = TRUE;
		    }
		}
		break;
	    case 'n':
		if(ARG2.val_Type == VTF_NUMBER)
		{
		    if((vw->vw_Prefs.prf_NoSnapshotWin = ARG2.val_Value.Number) > 1)
			memcpy(DefDims, vw->vw_Sleeping ? vw->vw_OldDimensions : &vw->vw_Window->LeftEdge, 2*4);
		    rc = TRUE;
		}
		break;
	    case 'p':
		if(ARG2.val_Type == VTF_STRING)
		{
		    strncpy(vw->vw_Prefs.prf_ScreenName, ARG2.val_Value.String, 100);
		    rc = TRUE;
		}
		break;
	}
    }
    if(rc != -1)
    {
	setnumres(rc);
    }
    else
	settitle("error: bad args to setpref");
    return(&RES);
}

VALUE *
cmd_getpref(LONG argc, VALUE *argv)
{
    if(ARG1.val_Type == VTF_STRING)
    {
	VW *vw = CurrVW;
	switch(tolower(*(ARG1.val_Value.String)))
	{
	    case 'a':   /* autoindent */
		setnumres(vw->vw_Prefs.prf_AutoIndent);
		break;
	    case 'd':   /* disktab */
		setnumres(vw->vw_Prefs.prf_DiskTab);
		break;
	    case 'f':   /* font */
		settitle("not implemented, sorry");
		break;
	    case 'l':   /* leftmargin */
		setnumres(vw->vw_Prefs.prf_LeftMargin);
		break;
	    case 'r':   /* rightmargin */
		if(!strcmp(ARG1.val_Value.String, "reset"))
		{
		    setnumres(vw->vw_Tx->tx_ResetPrefs);
		}
		else
		{
		    setnumres(vw->vw_Prefs.prf_RightMargin);
		}
		break;
	    case 't':   /* tabsize */
		setnumres(vw->vw_Prefs.prf_TabSize);
		break;
	    case 'w':   /* wordwrap */
		setnumres(vw->vw_Prefs.prf_WordWrap);
		break;
	    case 's':
		if(!strcmp(ARG1.val_Value.String, "saveprefs"))
		{
		    setnumres(SaveFilePrefs);
		}
		else if(ARG1.val_Value.String[1] == 'c')
		{
		    setnumres(ScrollHack);
		}
		else
		{
		    setnumres(vw->vw_Prefs.prf_SaveTabs);
		}
		break;
	    case 'b':
		if(!stricmp(ARG1.val_Value.String, "bakdir"))
		{
		    setstrres(savestring(vw->vw_Prefs.prf_BakDir));
		}
		else
		{
		     setnumres(vw->vw_Prefs.prf_MaxBak);
		}
		break;
	    case 'n':
		setnumres(vw->vw_Prefs.prf_NoSnapshotWin);
		break;
	    case 'p':
		STRPTR tmp = savestring(vw->vw_Prefs.prf_ScreenName);
		if(tmp)
		{
		    setstrres(tmp);
		}
		else
		    settitle(NoMemMsg);
		break;
	    default:
		settitlefmt("error: unrecognized pref %s", (LONG)ARG1.val_Value.String);
		break;
	}
    }
    else
	settitle("syntax error: argument 1 should be a string");
    return(&RES);
}

/*
 * (info `what')
 *
 * "what" can be,
 *	col
 *	line
 *	lines
 *	cols
 *	size
 *	offset
 *	changes
 *	views
 *	files
 *	windows
 *	char
 *	fullname
 *	filename
 *	dirname
 *	time
 *	date
 *	cd
 *	rev
 *	screenx		-- width of screen
 *	screeny		-- height of screen
 *	leftedge	-- x pos of window
 *	topedge
 *	width		-- width of window (pixels)
 *	height
 *	asleep
 *	port
 *	barheight
 */
VALUE *
cmd_info(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_STRING))
    {
	STRPTR what = ARG1.val_Value.String;
	VW *vw = CurrVW;
	TX *tx = vw->vw_Tx;

	if(!stricmp(what, "col"))
	{
	    setnumres(vw->vw_CursorPos.pos_Col + 1);
	}
	else if(!stricmp(what, "line"))
	{
	    setnumres(vw->vw_CursorPos.pos_Line + 1);
	}
	else if(!stricmp(what, "lines"))
	{
	    setnumres(tx->tx_NumLines);
	}
	else if(!stricmp(what, "cols"))
	{
	    setnumres(tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen);
	}
	else if(!stricmp(what, "size"))
	{
	    setnumres(size());
	}
	else if(!stricmp(what, "offset"))
	{
	    setnumres(offset());
	}
	else if(!stricmp(what, "changes"))
	{
	    setnumres(tx->tx_Changes);
	}
	else if(!stricmp(what, "views"))
	{
	    setnumres(numviews(tx));
	}
	else if(!stricmp(what, "files"))
	{
	    setnumres(numtxs());
	}
	else if(!stricmp(what, "windows"))
	{
	    setnumres(NumWindows);
	}
	else if(!stricmp(what, "char"))
	{
	    if(vw->vw_CursorPos.pos_Col < tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen)
	    {
		setnumres(tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Line[vw->vw_CursorPos.pos_Col]);
	    }
	    else
	    {
		setnumres(0);
	    }
	}
	else if(!stricmp(what, "fullname"))
	{
	    STRPTR name = savestring(tx->tx_FileName);
	    if(name)
	    {
		setstrres(name);
	    }
	    else
		settitle(NoMemMsg);
	}
	else if(!stricmp(what, "filename"))
	{
	    STRPTR name = savestring(FilePart(tx->tx_FileName));
	    if(name)
	    {
		setstrres(name);
	    }
	    else
		settitle(NoMemMsg);
	}
	else if(!stricmp(what, "dirname"))
	{
	    ULONG length;
	    STRPTR name;
	    length = FilePart(tx->tx_FileName) - tx->tx_FileName;
	    if(name = savestringn(tx->tx_FileName, length))
	    {
		setstrres(name);
	    }
	    else
		settitle(NoMemMsg);
	}
	else if(!stricmp(what, "time"))
	{
	    UBYTE buff[256];
	    struct DateTime date;

	    DateStamp(&date.dat_Stamp);
	    date.dat_Format = FORMAT_DOS;
	    date.dat_Flags = 0;
	    date.dat_StrDay = NULL;
	    date.dat_StrDate = NULL;
	    date.dat_StrTime = buff;

	    if(DateToStr(&date))
	    {
		STRPTR time = savestring(buff);
		if(time)
		{
		    setstrres(time);
		}
	    }
	}
	else if(!stricmp(what, "date"))
	{
	    UBYTE buff[256];
	    struct DateTime date;

	    DateStamp(&date.dat_Stamp);
	    date.dat_Format = FORMAT_DOS;
	    date.dat_Flags = 0;
	    date.dat_StrDay = NULL;
	    date.dat_StrDate = buff;
	    date.dat_StrTime = NULL;

	    if(DateToStr(&date))
	    {
		STRPTR date = savestring(buff);
		if(date)
		{
		    setstrres(date);
		}
	    }
	}
	else if(!stricmp(what, "cd"))
	{
	    UBYTE buff[256];
	    if(NameFromLock(((struct Process *)FindTask(0L))->pr_CurrentDir, buff ,256))
	    {
		STRPTR cd = savestring(buff);
		if(cd)
		{
		    setstrres(cd);
		}
	    }
	}
	else if(!stricmp(what, "rev"))
	{
	    setnumres(RELEASE);
	}
	else if(!stricmp(what, "screenx"))
	{
	    setnumres(vw->vw_Window->WScreen->Width);
	}
	else if(!stricmp(what, "screeny"))
	{
	    setnumres(vw->vw_Window->WScreen->Height);
	}
	else if(!stricmp(what, "leftedge"))
	{
	    setnumres(vw->vw_Window->LeftEdge);
	}
	else if(!stricmp(what, "topedge"))
	{
	    setnumres(vw->vw_Window->TopEdge);
	}
	else if(!stricmp(what, "width"))
	{
	    setnumres(vw->vw_Window->Width);
	}
	else if(!stricmp(what, "height"))
	{
	    setnumres(vw->vw_Window->Height);
	}
	else if(!stricmp(what, "asleep"))
	{
	    setnumres(vw->vw_Sleeping);
	}
	else if(!stricmp(what, "port"))
	{
	    STRPTR copy = savestring(RexxName);
	    if(copy)
		setstrres(copy);
	}
	else if(!stricmp(what, "barheight"))
	{
	    setnumres((LONG)vw->vw_Window->BorderTop);
	}
	else
	    settitlefmt("error: unknown info requested (%s)", (LONG)what);
    }
    return(&RES);
}
