home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
editor
/
beav
/
echo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-30
|
8KB
|
453 lines
/*
* Echo line reading and writing.
* Common routines for reading
* and writing characters in the echo line area
* of the display screen. Used by the entire
* known universe.
*/
#include "def.h"
void eerase ();
bool ereply ();
bool eread ();
void eformat ();
void eputi ();
void eputs ();
void eputc ();
extern char MSG_null[];
extern char MSG_y_n[];
extern char MSG_hex_dig[];
extern char MSG_hit_key[];
int epresf = FALSE; /* Stuff in echo line flag. */
/*
* Erase the echo line.
*/
void
eerase ()
{
writ_echo (MSG_null); /* clear the echo line */
epresf = FALSE;
}
/*
* Ask "yes" or "no" question.
* Return ABORT if the user answers the question
* with the abort ("^G") character. Return FALSE
* for "no" and TRUE for "yes". No formatting
* services are available.
*/
bool
eyesno (sp)
char *sp;
{
register bool s;
char buf[NCOL];
for (;;)
{
s = ereply (MSG_y_n, buf, sizeof (buf), sp);
if (s == ABORT)
return (ABORT);
if (s != FALSE)
{
if (buf[0] == 'y' || buf[0] == 'Y')
return (TRUE);
if (buf[0] == 'n' || buf[0] == 'N')
return (FALSE);
}
}
}
/*
* Write out a prompt, and read back a
* reply. The prompt is now written out with full "eprintf"
* formatting, although the arguments are in a rather strange
* place. This is always a new message, there is no auto
* completion, and the return is echoed as such.
*/
/* VARARGS3 */
bool
ereply (fp, buf, nbuf, arg)
char *fp;
char *buf;
int nbuf;
char *arg;
{
return (eread (fp, buf, nbuf, EFNEW | EFCR, arg));
}
/*
* This is the general "read input from the
* echo line" routine. The basic idea is that the prompt
* string "prompt" is written to the echo line, and a one
* line reply is read back into the supplied "buf" (with
* maximum length "len"). The "flag" contains EFNEW (a
* new prompt), an EFAUTO (autocomplete), or EFCR (echo
* the carriage return as CR).
*/
bool
eread (fp, buf, nbuf, flag, ap)
char *fp;
char *buf;
char *ap;
int nbuf, flag;
{
register int cpos;
register SYMBOL *sp1;
register SYMBOL *sp2;
register int i;
register int c;
register int h;
register int nhits;
register int nxtra;
register int bxtra;
int quote_flag;
quote_flag = 0;
cpos = 0;
if (kbdmop != NULL)
{
/* In a macro. */
while ((c = *kbdmop++) != '\0')
buf[cpos++] = c;
buf[cpos] = '\0';
goto done;
}
if ((flag & EFNEW) != 0 || ttrow != nrow - 1)
{
ttcolor (CTEXT);
ttmove (nrow - 1, 0);
epresf = TRUE;
}
else
eputc (' ');
eformat (fp, ap);
tteeol ();
ttflush ();
for (;;)
{
c = getkey ();
if (c == ' ' && (flag & EFAUTO) != 0)
{
nhits = 0;
nxtra = HUGE;
for (h = 0; h < NSHASH; ++h)
{
sp1 = symbol[h];
while (sp1 != NULL)
{
for (i = 0; i < cpos; ++i)
{
if (buf[i] != sp1->s_name[i])
break;
}
if (i == cpos)
{
if (nhits == 0)
sp2 = sp1;
++nhits;
bxtra = getxtra (sp1, sp2, cpos);
if (bxtra < nxtra)
nxtra = bxtra;
}
sp1 = sp1->s_symp;
}
}
if (nhits == 0) /* No completion. */
continue;
for (i = 0; i < nxtra && cpos < nbuf - 1; ++i)
{
c = sp2->s_name[cpos];
buf[cpos++] = c;
eputc (c);
}
ttflush ();
if (nhits != 1) /* Fake a CR if there */
continue; /* is 1 choice. */
c = (KCTRL | 'M');
}
if (quote_flag)
{
c = c & 0x1f;
quote_flag = 0;
}
switch (c)
{
case (KCTRL | 'Q'):
quote_flag = 1;
break;
case (KCTRL | 'M'): /* Return, done. */
case (KCTRL | 'J'): /* Linefeed, done. */
buf[cpos] = '\0';
if (kbdmip != NULL)
{
if (kbdmip + cpos + 1 > &kbdm[NKBDM - 3])
{
(void) ctrlg (FALSE, 0, KRANDOM);
ttflush ();
return (ABORT);
}
for (i = 0; i < cpos; ++i)
*kbdmip++ = buf[i];
*kbdmip++ = '\0';
}
if ((flag & EFCR) != 0)
{
ttputc (0x0D);
ttflush ();
}
goto done;
case (KCTRL | 'G'): /* Bell, abort. */
eputc (0x07);
(void) ctrlg (FALSE, 0, KRANDOM);
ttflush ();
return (ABORT);
case 0x7F: /* Rubout, erase. */
case (KCTRL | 'H'): /* Backspace, erase. */
if (cpos != 0)
{
ttputc ('\b');
ttputc (' ');
ttputc ('\b');
--ttcol;
if (ISCTRL (buf[--cpos]) != FALSE)
{
ttputc ('\b');
ttputc (' ');
ttputc ('\b');
--ttcol;
}
ttflush ();
}
break;
case (KCTRL | 'U'): /* C-U, kill line. */
while (cpos != 0)
{
ttputc ('\b');
ttputc (' ');
ttputc ('\b');
--ttcol;
if (ISCTRL (buf[--cpos]) != FALSE)
{
ttputc ('\b');
ttputc (' ');
ttputc ('\b');
--ttcol;
}
}
ttflush ();
break;
default: /* All the rest. */
if ((cpos < nbuf - 1) && ((c & ~KCHAR) == 0))
{
buf[cpos++] = c;
eputc (c);
ttflush ();
}
} /* End switch */
}
done:
if (buf[0] == '\0')
return (FALSE);
return (TRUE);
}
/*
* The "sp1" and "sp2" point to extended command
* symbol table entries. The "cpos" is a horizontal position
* in the name. Return the longest block of characters that can
* be autocompleted at this point. Sometimes the two symbols
* are the same, but this is normal.
*/
int
getxtra (sp1, sp2, cpos)
SYMBOL *sp1;
SYMBOL *sp2;
int cpos;
{
register int i;
i = cpos;
for (;;)
{
if (sp1->s_name[i] != sp2->s_name[i])
break;
if (sp1->s_name[i] == '\0')
break;
++i;
}
return (i - cpos);
}
/*
* Printf style formatting. This is
* called by both "eprintf" and "ereply", to provide
* formatting services to their clients. The move to the
* start of the echo line, and the erase to the end of
* the echo line, is done by the caller.
*/
void
eformat (fp, ap)
char *fp;
char *ap;
{
register int c;
while ((c = *fp++) != '\0')
{
if (c != '%')
eputc (c);
else
{
c = *fp++;
switch (c)
{
case 'd':
eputi (*(int *) ap, 10);
ap += sizeof (int);
break;
case 'x': /* krw */
eputi (*(int *) ap, 16);
ap += sizeof (int);
break;
case 'o':
eputi (*(int *) ap, 8);
ap += sizeof (int);
break;
case 's':
eputs (ap);
ap += sizeof (char *);
break;
default:
eputc (c);
}
}
}
}
/*
* Put integer, in radix "r".
*/
void
eputi (i, r)
int i;
int r;
{
static char *convert =
{
MSG_hex_dig
};
register int q;
if ((q = i / r) != 0)
eputi (q, r);
eputc (convert[i % r]);
}
/*
* Put string.
*/
void
eputs (s)
char *s;
{
register int c;
while ((c = *s++) != '\0')
eputc (c);
}
/*
* Put character. Watch for
* control characters, and for the line
* getting too long.
*/
void
eputc (c)
int c;
{
if (ttcol < ncol)
{
if (ISCTRL (c) != FALSE)
{
eputc ('^');
c ^= 0x40;
}
ttputc (c);
++ttcol;
}
}
/*
* Print warning message and wait for the user to hit a key.
*/
void
err_echo (buf)
char *buf;
{
char ch[NCOL * 2];
strcpy (ch, buf);
strcat (ch, MSG_hit_key);
writ_echo (ch);
ttbeep ();
while (ttgetc () != CTL_G);
{
ttbeep ();
ttflush ();
}
}