This is exconfig.c in view mode; [Download] [Up]
/* exconfig.c */
/* Copyright 1995 by Steve Kirkendall */
char id_exconfig[] = "$Id: exconfig.c,v 2.50 1996/09/21 02:12:31 steve Exp $";
#include "elvis.h"
static BOOLEAN thenflag; /* set by ":if", tested by ":then" & ":else" */
RESULT ex_args(xinf)
EXINFO *xinf;
{
int i, col, len;
char **tmp;
/* were we given a new args list? */
if (xinf->nfiles > 0)
{
/* yes, use it */
tmp = arglist;
arglist = xinf->file;
xinf->file = tmp;
for (xinf->nfiles = 0; xinf->file[xinf->nfiles]; xinf->nfiles++)
{
}
argnext = 0;
}
else
{
/* show current args list */
for (i = col = 0; arglist[i]; i++)
{
len = strlen(arglist[i]);
/* whitespace between args */
if (i == 0)
; /* no space is needed */
else if (col + len + 4 > o_columns(xinf->window))
{
drawextext(xinf->window, toCHAR("\n"), 1);
col = 0;
}
else
{
drawextext(xinf->window, toCHAR(" "), 1);
col++;
}
/* Output the arg. If current, enclose in '[' */
if (i == argnext - 1)
drawextext(xinf->window, toCHAR("["), 1);
drawextext(xinf->window, toCHAR(arglist[i]), len);
if (i == argnext - 1)
drawextext(xinf->window, toCHAR("]"), 1);
col += len;
}
/* the final newline */
drawextext(xinf->window, toCHAR("\n"), 1);
}
return RESULT_COMPLETE;
}
/* This table stores the names of the fonts, and the colors assigned to
* them. Initially the colors are NULL. A foreground and background are
* stored for each, although some GUIs don't allow that much control.
*/
static struct
{
char *name; /* name of the font to be colorized */
CHAR *fg; /* name of foreground color */
CHAR *bg; /* name of background color */
} colortbl[] =
{
{"normal"}, {"bold"}, {"emphasized"}, {"italic"},
{"underlined"}, {"fixed"}, {"cursor"}, {"standout"},
{"scrollbar"} /* "scrollbar" must be last */
};
/* This function implements the :color command. */
RESULT ex_color(xinf)
EXINFO *xinf;
{
CHAR *args, *cp, *bg;
int i, j;
if (!gui->color)
{
msg(MSG_ERROR, "no color support");
return RESULT_ERROR;
}
if (!xinf->rhs)
{
/* list any colors which have been set */
for (i = j = 0; i < QTY(colortbl); i++)
{
if (colortbl[i].fg && colortbl[i].bg)
msg(MSG_INFO, "[sSS]color $1 $2 on $3",
colortbl[i].name, colortbl[i].fg,
colortbl[i].bg);
else if (colortbl[i].fg)
msg(MSG_INFO, "[sS]color $1 $2",
colortbl[i].name, colortbl[i].fg);
else
j++;
}
if (i == j)
msg(MSG_WARNING, "no colors have been set");
return RESULT_COMPLETE;
}
/* PARSE ARGS INTO FONT, FOREGROUND & BACKGROUND */
/* font... */
args = xinf->rhs;
if (!CHARncmp(args, toCHAR("s "), 2) && gui->scrollbar)
{
i = QTY(colortbl) - 1;
}
else
{
for (i = 0;
i < QTY(colortbl)
&& (CHARncmp(toCHAR(colortbl[i].name), args, strlen(colortbl[i].name)) || args[strlen(colortbl[i].name)] != ' ')
&& !(args[0] == (CHAR)colortbl[i].name[0] && args[1] == ' ');
i++)
{
}
}
if (i >= QTY(colortbl))
{
i = 0; /* if no name given, assume "normal" */
}
else
{
/* skip past the name */
while (*args != ' ')
{
args++;
}
while (*args == ' ')
{
args++;
}
}
/* foreground & background... */
for (bg = args; *bg && strncmp(tochar8(bg), " on ", 4); bg++)
{
}
if (*bg)
{
*bg = '\0';
for (bg += 4; *bg && isspace(*bg); bg++)
{
}
}
if (!*bg)
{
bg = (CHAR *)0;
}
/* trim trailing whitespace */
for (cp = args + CHARlen(args); --cp >= args && isspace(*cp); )
{
*cp = '\0';
}
if (!*args)
{
msg(MSG_ERROR, "missing foreground color");
return RESULT_ERROR;
}
/* call the GUI's color function */
if ((*gui->color)(xinf->window ? xinf->window->gw : (GUIWIN *)0, colortbl[i].name[0], args, bg))
{
/* redraw the window */
if (xinf->window)
{
xinf->window->di->logic = DRAW_SCRATCH;
}
/* remember the chosen colors */
if (colortbl[i].fg)
safefree(colortbl[i].fg);
colortbl[i].fg = args ? CHARdup(args) : NULL;
if (colortbl[i].bg)
safefree(colortbl[i].bg);
colortbl[i].bg = bg ? CHARdup(bg) : NULL;
return RESULT_COMPLETE;
}
return RESULT_ERROR;
}
void colorsave(custom)
BUFFER custom; /* where to stuff the color commands */
{
MARKBUF m;
int i;
char tmp[80];
/* try to make colors GUI-sensitive */
sprintf(tmp, "if gui==\"%s\"\n", tochar8(o_gui));
bufreplace(marktmp(m, custom, o_bufchars(custom)), &m, toCHAR(tmp), (long)strlen(tmp));
/* store the color commands */
for (i = 0; i < QTY(colortbl); i++)
{
if (colortbl[i].fg)
{
sprintf(tmp, "then color %s %s", colortbl[i].name, tochar8(colortbl[i].fg));
if (colortbl[i].bg)
{
strcat(tmp, " on ");
strcat(tmp, tochar8(colortbl[i].bg));
}
strcat(tmp, "\n");
bufreplace(marktmp(m, custom, o_bufchars(custom)), &m, toCHAR(tmp), (long)strlen(tmp));
}
}
}
RESULT ex_comment(xinf)
EXINFO *xinf;
{
CHAR *result;
assert(xinf->command == EX_COMMENT || xinf->command == EX_ECHO
|| xinf->command == EX_CALC || xinf->command == EX_GOTO);
if (xinf->command == EX_ECHO && xinf->rhs)
{
drawextext(xinf->window, xinf->rhs, (int)CHARlen(xinf->rhs));
drawextext(xinf->window, toCHAR("\n"), 1);
}
else if (xinf->command == EX_CALC && xinf->rhs)
{
result = calculate(xinf->rhs, NULL, False);
if (!result)
{
return RESULT_ERROR;
}
drawextext(xinf->window, result, (int)CHARlen(result));
drawextext(xinf->window, toCHAR("\n"), 1);
}
else if (xinf->command == EX_GOTO && xinf->fromaddr)
{
if (xinf->fromoffset > markoffset(xinf->fromaddr)
&& xinf->fromoffset <= markoffset(xinf->toaddr))
xinf->newcurs = markalloc(markbuffer(xinf->fromaddr), xinf->fromoffset);
else
xinf->newcurs = markdup(xinf->fromaddr);
}
return RESULT_COMPLETE;
}
RESULT ex_digraph(xinf)
EXINFO *xinf;
{
digaction(xinf->window, xinf->bang, xinf->rhs);
return RESULT_COMPLETE;
}
RESULT ex_display(xinf)
EXINFO *xinf;
{
if (xinf->command == EX_DISPLAY && !xinf->rhs)
{
displist(xinf->window);
}
else if (!dispset(xinf->window, tochar8(xinf->rhs)))
{
return RESULT_ERROR;
}
xinf->window->di->logic = DRAW_CHANGED;
return RESULT_COMPLETE;
}
RESULT ex_gui(xinf)
EXINFO *xinf;
{
if (!gui->guicmd)
{
msg(MSG_ERROR, "gui-specific commands not supported");
return RESULT_ERROR;
}
return (*gui->guicmd)(xinf->window ? xinf->window->gw : NULL, tochar8(xinf->rhs))
? RESULT_COMPLETE
: RESULT_ERROR;
}
RESULT ex_help(xinf)
EXINFO *xinf;
{
#ifndef DISPLAY_MARKUP
msg(MSG_ERROR, "help unavailable; html mode is disabled");
return RESULT_ERROR;
#else
CHAR *topic; /* topic to search for; a tag name */
char *section;/* name of help file containing topic */
CHAR *tag; /* name of tag to search for -- section#topic */
BUFFER buf; /* buffer containing help text */
MARK tagdefn;/* result of search; where cursor should move to */
int i;
/* construct a tag name for the requested topic */
topic = NULL;
if (!xinf->lhs)
{
/* :help */
topic = toCHAR("CONTENTS");
section = "elvis.html";
}
else if (!CHARcmp(xinf->lhs, toCHAR("ex")))
{
/* :help ex */
section = "elvisex.html";
}
else if (!CHARcmp(xinf->lhs, toCHAR("vi")))
{
/* :help vi */
section = "elvisvi.html";
}
else if ((!CHARncmp(xinf->lhs, toCHAR("se"), 2)
|| !CHARncmp(xinf->lhs, toCHAR(":se"), 3))
&& xinf->rhs)
{
/* :help set optionname */
topic = optname(xinf->rhs);
if (!topic)
topic = toCHAR("GROUP");
section = "elvisopt.html";
}
else if (CHARlen(xinf->lhs) > 1 && xinf->lhs[0] == ':')
{
/* :help :exname */
topic = exname(xinf->lhs + 1);
if (!topic)
topic = toCHAR("GROUP");
section = "elvisex.html";
}
else if ((topic = viname(xinf->lhs)) != NULL)
{
/* :help c (where c is a vi command, usually single-char) */
section = "elvisvi.html";
}
else if ((topic = optname(xinf->lhs)) != NULL)
{
/* :help optionname */
section = "elvisopt.html";
}
else if ((topic = exname(xinf->lhs)) != NULL)
{
/* :help exname */
section = "elvisex.html";
}
else
{
/* Can't tell what user is looking for; perhaps the user
* doesn't know the syntax of :help ? Teach them!
*/
topic = toCHAR("help");
section = "elvisex.html";
}
/* if help text not found, then give up */
buf = bufpath(o_elvispath, section, toCHAR(section));
if (!buf)
{
msg(MSG_ERROR, "[s]help not available; couldn't load $1", section);
return RESULT_ERROR;
}
/* help text uses "html" display mode */
if (optflags(o_bufdisplay(buf)) & OPT_FREE)
{
safefree(o_bufdisplay(buf));
optflags(o_bufdisplay(buf)) &= ~OPT_FREE;
}
o_bufdisplay(buf) = toCHAR("html");
/* combine section name and topic name to form a tag */
if (topic)
{
tag = safealloc((int)(CHARlen(o_filename(buf)) + CHARlen(topic) + 2), sizeof(CHAR));
CHARcpy(tag, o_filename(buf));
CHARcat(tag, toCHAR("#"));
CHARcat(tag, topic);
}
else
{
tag = CHARdup(toCHAR(section));
}
/* perform tag lookup to find the the topic in the help file */
tagdefn = (*dmhtml.tagload)(tag, NULL);
if (!tagdefn)
{
msg(MSG_ERROR, "[S]no help available for $1", topic);
safefree(tag);
return RESULT_ERROR;
}
safefree(tag);
/* Try to create a new window for the help text. If that doesn't
* work, then use the original window and push the old cursor onto
* the tag stack.
*/
markbuffer(tagdefn)->changepos = markoffset(tagdefn);
if ((*gui->creategw)(tochar8(o_bufname(markbuffer(tagdefn))), ""))
{
return RESULT_COMPLETE;
}
/* push the current cursor position and display mode onto tag stack */
if (o_tagstack &&
!o_internal(markbuffer(xinf->window->cursor)) &&
o_filename(markbuffer(xinf->window->cursor)))
{
for (i = TAGSTK - 1; i > 0; i--)
{
xinf->window->tagstack[i] = xinf->window->tagstack[i - 1];
}
xinf->window->tagstack[0].prevtag = (o_previoustag ? CHARdup(o_previoustag) : NULL);
xinf->window->tagstack[0].origin = markdup(xinf->window->cursor);
xinf->window->tagstack[0].display = xinf->window->md->name;
}
/* arrange for the cursor to move to the tag position */
xinf->newcurs = markdup(tagdefn);
return RESULT_COMPLETE;
#endif
}
/* Evaluate an expression, and set the "then" flag according to result */
RESULT ex_if(xinf)
EXINFO *xinf;
{
CHAR *result;
/* expression is required */
if (!xinf->rhs)
{
msg(MSG_ERROR, "missing rhs");
return RESULT_ERROR;
}
/* evaluate expression */
result = calculate(xinf->rhs, NULL, (BOOLEAN)(xinf->command == EX_EVAL));
if (!result)
{
return RESULT_ERROR;
}
if (xinf->command == EX_IF)
{
/* set "thenflag" based on result of evaluation */
thenflag = calctrue(result);
return RESULT_COMPLETE;
}
else /* command == EX_EVAL */
{
/* execute the result as an ex command */
return exstring(xinf->window, result);
}
}
RESULT ex_then(xinf)
EXINFO *xinf;
{
BOOLEAN origthen;
RESULT result;
origthen = thenflag;
result = RESULT_COMPLETE;
/* Execute commands, if "thenflag" is set appropriately */
if (xinf->command == EX_THEN ? thenflag : !thenflag)
{
result = exstring(xinf->window, xinf->rhs);
}
/* If the command line was enclosed in { .... } (as indicated by the
* presence of a newline; without curlies the command couldn't possibly
* contain any newlines) then restore the "thenflag" to its original
* value.
*/
if (CHARchr(xinf->rhs, '\n'))
{
thenflag = origthen;
}
return result;
}
/* This implemented :map, :unmap, :abbr, :unabbr, :break, and :unbreak */
RESULT ex_map(xinf)
EXINFO *xinf;
{
CHAR *line;
MAPFLAGS flags;
int len;
assert(xinf->command == EX_MAP || xinf->command == EX_ABBR
|| xinf->command == EX_UNMAP || xinf->command == EX_UNABBR
|| xinf->command == EX_BREAK || xinf->command == EX_UNBREAK);
/* check for missing mandatory arguments */
if ((xinf->command == EX_MAP || xinf->command == EX_ABBR)
&& xinf->lhs && !xinf->rhs)
{
msg(MSG_ERROR, "missing rhs");
return RESULT_ERROR;
}
if ((xinf->command == EX_UNMAP || xinf->command == EX_UNABBR
|| xinf->command == EX_BREAK || xinf->command == EX_UNBREAK)
&& !xinf->lhs)
{
msg(MSG_ERROR, "missing lhs");
return RESULT_ERROR;
}
/* choose which flags to map */
if (xinf->command == EX_ABBR || xinf->command == EX_UNABBR)
{
flags = MAP_ABBR|(xinf->bang ? MAP_COMMAND : MAP_INPUT);
}
else if (xinf->rhs && !CHARncmp(xinf->rhs, toCHAR("visual "), 7))
{
flags = (MAP_INPUT|MAP_ASCMD|MAP_OPEN);
if (!xinf->bang)
flags |= MAP_COMMAND;
}
else
{
flags = xinf->bang ? (MAP_INPUT|MAP_OPEN) : MAP_COMMAND;
}
/* either list, unmap, or map */
if (!xinf->lhs)
{
while ((line = maplist(flags & (MAP_INPUT|MAP_COMMAND|MAP_ABBR), &len)) != (CHAR *)0)
{
/* can't list maps before the first window is created */
if (xinf->window)
drawextext(xinf->window, line, len);
}
}
else if (!xinf->rhs)
{
(void)mapdelete(xinf->lhs, (int)CHARlen(xinf->lhs), flags,
(BOOLEAN)(xinf->command == EX_UNMAP || xinf->command == EX_UNABBR),
(BOOLEAN)(xinf->command == EX_BREAK));
}
else
{
mapinsert(xinf->lhs, (int)CHARlen(xinf->lhs), xinf->rhs, (int)CHARlen(xinf->rhs), (CHAR *)0, flags);
}
return RESULT_COMPLETE;
}
RESULT ex_set(xinf)
EXINFO *xinf;
{
CHAR outbuf[5000];
static CHAR empty[1];
int i;
if (xinf->command == EX_LET)
{
i = 0;
if (!xinf->rhs)
{
goto MissingRHS;
}
/* copy name into outbuf[], so we can nul-terminate it */
for ( ; xinf->rhs && isalnum(xinf->rhs[i]); i++)
{
outbuf[i] = xinf->rhs[i];
}
outbuf[i] = '\0';
/* skip whitespace */
while (isspace(xinf->rhs[i]))
{
i++;
}
/* skip '=' */
if (xinf->rhs[i] != '=' || !outbuf[0])
{
goto MissingRHS;
}
i++;
/* skip whitespace after the '=' */
while (isspace(xinf->rhs[i]))
{
i++;
}
if (!xinf->rhs[i])
{
MissingRHS:
msg(MSG_ERROR, "missing rhs");
return RESULT_ERROR;
}
/* evaluate & store the result */
if (!optputstr(outbuf, calculate(&xinf->rhs[i], NULL, False)))
{
return RESULT_ERROR;
}
}
else /* command == EX_SET */
{
if (!optset(xinf->bang, xinf->rhs ? xinf->rhs : empty, outbuf, QTY(outbuf)))
{
return RESULT_ERROR;
}
if (*outbuf)
{
drawextext(windefault, outbuf, (int)CHARlen(outbuf));
}
}
return RESULT_COMPLETE;
}
RESULT ex_version(xinf)
EXINFO *xinf;
{
msg(MSG_INFO, "[s]elvis $1", VERSION);
#ifdef COPY1
msg(MSG_INFO, "[s]$1", COPY1);
#endif
#ifdef COPY2
msg(MSG_INFO, "[s]$1", COPY2);
#endif
#ifdef COPY3
msg(MSG_INFO, "[s]$1", COPY3);
#endif
#ifdef COPY4
msg(MSG_INFO, "[s]$1", COPY4);
#endif
#ifdef PORTEDBY
msg(MSG_INFO, "[s]$1", PORTEDBY);
#endif
return RESULT_COMPLETE;
}
RESULT ex_qall(xinf)
EXINFO *xinf;
{
WINDOW win;
WINDOW orig;
RESULT result;
BOOLEAN didorig;
assert(xinf->command == EX_QALL || xinf->command == EX_PRESERVE);
/* If :preserve, then turn off the tempsession flag */
if (xinf->command == EX_PRESERVE)
{
o_tempsession = False;
}
/* Perform a :quit command on each window in turn. */
xinf->command = EX_QUIT;
orig = xinf->window;
for (win = winofbuf(NULL, NULL), result = RESULT_COMPLETE, didorig = False;
win;
win = winofbuf(win, NULL))
{
xinf->window = win;
if (ex_xit(xinf) != RESULT_COMPLETE)
{
result = RESULT_ERROR;
}
else if (win != orig)
{
/* Need to explicitly delete all windows except the
* current one. The current one will go away
* automatically when the ex_qall() function exits.
*/
(*gui->destroygw)(win->gw, False);
win = didorig ? orig : NULL;
}
else
{
didorig = True;
}
}
return result;
}
RESULT ex_xit(xinf)
EXINFO *xinf;
{
BUFFER buf; /* the buffer to be saved */
MARKBUF top, bottom;
STATE *state;
BUFFER b; /* other buffers */
static long morechgs; /* change counter at last "more files" warning */
static BUFFER morebuf; /* buffer which morechgs value refers to */
assert(xinf->command == EX_CLOSE || xinf->command == EX_QUIT
|| xinf->command == EX_XIT || xinf->command == EX_WQUIT);
/* Save the buffer, if :wquit or modified and :xit */
buf = markbuffer(xinf->window->cursor);
if (xinf->command == EX_WQUIT ||
(o_modified(buf) && xinf->command == EX_XIT))
{
/* Write to named file or the buffer's original file.
* If can't write, then fail.
*/
if (xinf->nfiles == 1
? !bufwrite(marktmp(top, buf, 0), marktmp(bottom, buf, o_bufchars(buf)), xinf->file[0], xinf->bang)
: !bufsave(buf, xinf->bang, True))
{
/* an error message has already been output */
return RESULT_ERROR;
}
}
/* if :q without a !, then complain if the buffer is modified */
if (xinf->command == EX_QUIT && !xinf->bang && o_modified(buf))
{
msg(MSG_ERROR, "[S]$1 modified, not saved", o_bufname(buf));
return RESULT_ERROR;
}
/* If this is the last window, then make sure *ALL* user buffers
* have been saved. Exception: If :close! and this session isn't
* temporary, then we don't need to check buffers.
*/
if ((morebuf != markbuffer(xinf->window->cursor) || morebuf->changes != morechgs)
&& !(xinf->command == EX_CLOSE && xinf->bang && o_tempsession)
&& winofbuf(NULL, NULL) == xinf->window && !winofbuf(xinf->window, NULL))
{
/* remember some stuff which should prevent us from warning
* the user more than once.
*/
morebuf = markbuffer(xinf->window->cursor);
morechgs = morebuf->changes;
/* check all buffers */
for (b = buffers; b; b = buflist(b))
{
if (!o_internal(b) && o_modified(b)
&& (xinf->command == EX_CLOSE || b != buf))
{
/* We've found a modified, unsaved user buffer.
* If the command is :q! then we want to
* discard all buffers; otherwise we want to
* warn the user that other buffers need to
* be checked.
*/
if (xinf->command == EX_QUIT && xinf->bang)
o_modified(b) = False;
else
{
msg(MSG_ERROR, "check other buffers");
return RESULT_ERROR;
}
}
}
/* also check for more files to edit */
if (arglist && (argnext < 0 || arglist[argnext])
&& (xinf->command != EX_QUIT || !xinf->bang))
{
msg(MSG_WARNING, "more files");
return RESULT_ERROR;
}
}
/* Arrange for the state stack to pop everything */
for (state = xinf->window->state; state; state = state->pop)
{
state->flags |= ELVIS_POP;
}
return RESULT_COMPLETE;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.