|
|
|
/*****************************************************************************
|
|
|
|
zosx.c
|
|
|
|
System dependent code for Mac OS X
|
|
|
|
This is based on zunix.c, with changes (see comments "TAA")
|
|
|
|
for enhanced functionality.
|
|
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
|
|
* Define standard functions.
|
|
|
|
*/
|
|
|
|
#include <sys/types.h> /* needed before sys/param.h is included */
|
|
|
|
#include <errno.h> /* define errno */
|
|
|
|
#include <signal.h> /* to catch ^C and ^Z signals */
|
|
|
|
#include <stdio.h> /* define stdin */
|
|
|
|
#include <string.h> /* strncpy(), strlen(), etc. */
|
|
|
|
#include <sys/time.h> /* define tm struct */
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <glob.h> /* Rewritten 05/04 by TAA to use glob function */
|
|
|
|
#if CURSES
|
|
|
|
#include <curses.h> /* has to come before zport.h */
|
|
|
|
#endif
|
|
|
|
#include "zport.h" /* define portability identifiers */
|
|
|
|
#include "tecoc.h" /* define general identifiers */
|
|
|
|
#include "chmacs.h" /* define character processing macros */
|
|
|
|
#include "clpars.h" /* command-line parsing macro */
|
|
|
|
#include "dchars.h" /* define identifiers for characters */
|
|
|
|
#include "deferr.h" /* define identifiers for error messages */
|
|
|
|
#include "defext.h" /* define external global variables */
|
|
|
|
#include "dscren.h" /* define identifiers for screen i/o */
|
|
|
|
#if CURSES
|
|
|
|
/*
|
|
|
|
* The ACS_xxx symbols are defined in the SunOS version of curses, but not
|
|
|
|
* in either the BSD or X/OPEN Ultrix versions. Who knows where else they
|
|
|
|
* are defined? Isn't portability wonderful?
|
|
|
|
*
|
|
|
|
* Note that this code implicitly assumes a VT100-compatible terminal.
|
|
|
|
* Tough. (Jerry Leichter, June 1991)
|
|
|
|
*/
|
|
|
|
#ifndef ACS_PLMINUS
|
|
|
|
#define ACS_PLMINUS (A_ALTCHARSET | 0x67)
|
|
|
|
#define ACS_LLCORNER (A_ALTCHARSET | 0x60)
|
|
|
|
#define ACS_LRCORNER (A_ALTCHARSET | 0x6A)
|
|
|
|
#define ACS_LARROW (A_ALTCHARSET | 0x7C) /* Really not-equal */
|
|
|
|
#define ACS_HLINE (A_ALTCHARSET | 0x71)
|
|
|
|
#define ACS_BTEE (A_ALTCHARSET | 0x76)
|
|
|
|
#define ACS_DIAMOND (A_ALTCHARSET | 0x60)
|
|
|
|
#define ACS_RTEE (A_ALTCHARSET | 0x75)
|
|
|
|
#endif
|
|
|
|
WINDOW *curwin;
|
|
|
|
int ScopeFlg = 0; /* for ZDspCh and ZDspBuf */
|
|
|
|
int olddot;
|
|
|
|
#define DOT (GapBeg - EBfBeg)
|
|
|
|
#define ISSCW (ScopeFlg)
|
|
|
|
unsigned char *p_scope_start;
|
|
|
|
int scope_start;
|
|
|
|
int winline;
|
|
|
|
int cursoratbottomline;
|
|
|
|
int cursorattopline;
|
|
|
|
static int colsave;
|
|
|
|
int dotx,doty; /* position of cursor in scope */
|
|
|
|
int dotx1, doty1; /* pos. after printing character in scope */
|
|
|
|
int skiprefresh = 0;
|
|
|
|
int cmdx,cmdy; /* position of cursor in command buffer */
|
|
|
|
int scope_start, scope_end;
|
|
|
|
unsigned char *pscope_start;
|
|
|
|
#define CT ((EzFlag & EZ_VT100GRAPHICS) ? ACS_PLMINUS : '^')
|
|
|
|
#define LB ((EzFlag & EZ_VT100GRAPHICS) ? ACS_LLCORNER : '[')
|
|
|
|
#define RB ((EzFlag & EZ_VT100GRAPHICS) ? ACS_LRCORNER : ']')
|
|
|
|
#else /* else (not CURSES) ----------------------*/
|
|
|
|
#ifdef LINUX
|
|
|
|
static struct termios out, cur; /* terminal characteristics buffers */
|
|
|
|
#else
|
|
|
|
#include <sgtty.h> /* define CBREAK, ECHO, TIOCGETP, etc. */
|
|
|
|
static struct sgttyb out, cur; /* terminal characteristics buffers */
|
|
|
|
#endif
|
|
|
|
static char tbuf[1024]; /* store TERMCAP entry here */
|
|
|
|
static char tarea[1024]; /* store decoded TERMCAP stuff here */
|
|
|
|
static char *ce; /* TERMCAP sequence: clear to end-of-line */
|
|
|
|
static char *up; /* TERMCAP sequence: cursor up */
|
|
|
|
static char *so; /* TERMCAP sequence: reverse video on */
|
|
|
|
static char *se; /* TERMCAP sequence: reverse video off */
|
|
|
|
int tputs(); /* send termcap string to a given function */
|
|
|
|
int tgetent(); /* load a terminal capability buffer */
|
|
|
|
char *tgetstr(); /* get str value of a terminal capability */
|
|
|
|
#endif
|
|
|
|
static BOOLEAN tty_set = FALSE; /* Has the terminal been set? */
|
|
|
|
static struct termios out, cur; /* terminal characteristics buffers */
|
|
|
|
static char tbuf[1024]; /* store TERMCAP entry here */
|
|
|
|
// static char tarea[1024]; /* store decoded TERMCAP stuff here */
|
|
|
|
// static char *ce; /* TERMCAP sequence: clear to end-of-line */
|
|
|
|
// static char *up; /* TERMCAP sequence: cursor up */
|
|
|
|
// static char *so; /* TERMCAP sequence: reverse video on */
|
|
|
|
// static char *se; /* TERMCAP sequence: reverse video off */
|
|
|
|
int tputs(); /* send termcap string to a given function */
|
|
|
|
int tgetent(); /* load a terminal capability buffer */
|
|
|
|
char *tgetstr(); /* get str value of a terminal capability */
|
|
|
|
static int vernum(); /* see bottom of this file */
|
|
|
|
//extern int sys_nerr; /* number of system error messages */
|
|
|
|
static int SupGotCtC = 0;
|
|
|
|
static glob_t pglob;
|
|
|
|
static int globindex = 0;
|
|
|
|
/*****************************************************************************
|
|
|
|
IFiles holds the file data blocks for input files. There are three
|
|
|
|
static input streams: the primary input stream, the secondary input stream,
|
|
|
|
and the input stream used by the EQq command. To access these three files,
|
|
|
|
identifiers defined in file tecoc.h are used to index into this array.
|
|
|
|
Other elements of this array are used to access input files for the EI
|
|
|
|
command.
|
|
|
|
*****************************************************************************/
|
|
|
|
FILE *IFiles[NIFDBS];
|
|
|
|
/* TAA Mod 5/04 -- keep track of last character being CR so we will
|
|
|
|
* have CRLF -> CRLF instead of CRLFLF in case input file is DOS
|
|
|
|
* format. */
|
|
|
|
static int IFisCR[NIFDBS] = {0};
|
|
|
|
/*****************************************************************************
|
|
|
|
OFiles holds the file data blocks for the output files. There are
|
|
|
|
three output streams: the primary output stream, the secondary output
|
|
|
|
stream and the output stream used by the E%q command. The array is indexed
|
|
|
|
using identifiers defined in file tecoc.h.
|
|
|
|
*****************************************************************************/
|
|
|
|
static struct {
|
|
|
|
char OFNam[FILENAME_MAX]; /* output file name */
|
|
|
|
char OTNam[FILENAME_MAX]; /* temporary output file name */
|
|
|
|
FILE *OStrem; /* stream */
|
|
|
|
BOOLEAN forBackup; /* TAA Mod */
|
|
|
|
} OFiles[NOFDBS];
|
|
|
|
/*****************************************************************************
|
|
|
|
ZErMsg()
|
|
|
|
This function displays error message from the operating system on
|
|
|
|
the terminal screen. The error message text is retrieved from the operating
|
|
|
|
system and imbedded in a TECO-style message with the SYS mnemonic.
|
|
|
|
*****************************************************************************/
|
|
|
|
static VVOID ZErMsg()
|
|
|
|
{
|
|
|
|
if (errno < sys_nerr)
|
|
|
|
ErrStr(ERR_SYS, sys_errlist[errno]);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZAlloc()
|
|
|
|
This function allocates memory. The single argument is the number of
|
|
|
|
bytes to allocate. TECO-C uses the ZFree and ZRaloc functions to de-allocate
|
|
|
|
and re-allocate, respectively, the memory allocated by this function.
|
|
|
|
*****************************************************************************/
|
|
|
|
voidptr ZAlloc(MemSize) /* allocate memory */
|
|
|
|
SIZE_T MemSize;
|
|
|
|
{
|
|
|
|
return (voidptr)malloc(MemSize);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZBell()
|
|
|
|
Thus function rings the terminal bell. For most platforms, this
|
|
|
|
means just writing a bell character (control-G) to the terminal. Under
|
|
|
|
MS-DOS, ringing the bell this way produces a yucky sound, so for MS-DOS
|
|
|
|
this function controls the signal generator directly.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZBell(VVOID)
|
|
|
|
{
|
|
|
|
#if CURSES
|
|
|
|
if (EzFlag & EZ_AUDIO_BEEP)
|
|
|
|
beep(); /* audio beep */
|
|
|
|
else
|
|
|
|
flash(); /* visible flash */
|
|
|
|
#else
|
|
|
|
ZDspCh('\7');
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZChIn()
|
|
|
|
This function inputs a single character from the terminal.
|
|
|
|
1. the character is not echoed on the terminal
|
|
|
|
2. ^C calls an interrupt routine. Note that this must be
|
|
|
|
implemented so that a ^C will cancel a current output via
|
|
|
|
ZDspBf. The ^C must be a true interrupt.
|
|
|
|
3. type-ahead is always nice
|
|
|
|
4. The character must be returned immediately: no fooling
|
|
|
|
around waiting for a carriage-return before returning.
|
|
|
|
5. If the NoWait argument is TRUE, don't wait.
|
|
|
|
6. When the user hits the RETURN key, TECO is supposed to see
|
|
|
|
a carriage return and then a line feed. The function must
|
|
|
|
deal with this by returning a carriage return to the caller
|
|
|
|
and then "remembering" to send a line feed on the next call.
|
|
|
|
7. handle ET_BKSP_IS_DEL flag
|
|
|
|
*****************************************************************************/
|
|
|
|
DEFAULT ZChIn(NoWait) /* input a character from terminal */
|
|
|
|
BOOLEAN NoWait; /* return immediately? */
|
|
|
|
{
|
|
|
|
char Charac;
|
|
|
|
static BOOLEAN LastLF = FALSE;
|
|
|
|
if (LastLF) {
|
|
|
|
LastLF = FALSE;
|
|
|
|
return (DEFAULT)LINEFD;
|
|
|
|
}
|
|
|
|
#if CURSES
|
|
|
|
if ((Charac = getch()) == ERR) {
|
|
|
|
#else
|
|
|
|
if (read(fileno(stdin), &Charac, 1) != 1) {
|
|
|
|
#endif
|
|
|
|
if (GotCtC || SupGotCtC)
|
|
|
|
return (DEFAULT)CTRL_C;
|
|
|
|
if (!GotCtC) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_URC);
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GotCtC = FALSE;
|
|
|
|
if (Charac == CRETRN) {
|
|
|
|
LastLF = TRUE;
|
|
|
|
return (DEFAULT)CRETRN;
|
|
|
|
}
|
|
|
|
if (EtFlag & ET_BKSP_IS_DEL) {
|
|
|
|
if (Charac == DELETE) {
|
|
|
|
Charac = BAKSPC;
|
|
|
|
} else if (Charac == BAKSPC) {
|
|
|
|
Charac = DELETE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (DEFAULT)Charac;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZClnEG()
|
|
|
|
This function executes a :EG command. The :EG commands are used to
|
|
|
|
get access to operating system functions. The minimum set of functions is
|
|
|
|
:EGINI$ gets, sets or clears the initialization file name
|
|
|
|
:EGMEM$ gets, sets or clears the file name memory
|
|
|
|
:EGLIB$ gets, sets or clears the macro library directory
|
|
|
|
:EGVTE$ gets, sets or clears the video macro file name
|
|
|
|
although more functions may be defined.
|
|
|
|
The :EG command was designed to access logical names, which are supported
|
|
|
|
by DEC's VAX/VMS and RSX operating systems. Logical names are a useful way
|
|
|
|
to specify, for example, a directory that a program is to find a set of files
|
|
|
|
in. A user can define logical names to set up a program's environment.
|
|
|
|
Programs can read, create or delete logical names.
|
|
|
|
Logical names are stored separately from program memory, so if a program sets
|
|
|
|
a logical name and then exits, the logical name still exists. TECO on a VAX
|
|
|
|
uses a logical name to store the name of the file being edited. If the user
|
|
|
|
starts TECO without specifying a file name, TECO looks for the logical name
|
|
|
|
and, if it exists, uses the value of the logical name as a filename. This
|
|
|
|
allows users to edit a file several times in a session without having to
|
|
|
|
type the file name each time they start TECO (except the first time).
|
|
|
|
Unix doesn't have logical names. The closest thing is environment variables,
|
|
|
|
which are passed to a program when it is started. A user can define
|
|
|
|
environment variables, and a program can get the values with a getenv call.
|
|
|
|
A program can even add to it's private list of environment variables, but
|
|
|
|
the list disappears when the program exits. So environment variables don't
|
|
|
|
fill the needs of the :EG command.
|
|
|
|
Environment variables are, however, natural for some of what :EG is really
|
|
|
|
used for. Users rarely need the :EG command, even in macros. The main use
|
|
|
|
of :EG is in the command-line-parsing macro (in CLPARS.TES, CLPARS.TEC and
|
|
|
|
CLPARS.H). That macro can handle a partially-implemented :EG command (it
|
|
|
|
tests the success/failure flag returned by :EG).
|
|
|
|
So I partially implemented :EG for Unix. :EG can read the "INI", "LIB" and
|
|
|
|
"VTE" values, but can't set or clear them. The "MEM" value is supported
|
|
|
|
using a file (ugh) to save the name of the last-file-edited. The file is
|
|
|
|
stored in /tmp so it gets deleted when the system boots.
|
|
|
|
*****************************************************************************/
|
|
|
|
LONG ZClnEG( /* execute special :EG command */
|
|
|
|
DEFAULT EGWhat, /* what to get/set/clear: MEM, LIB, etc. */
|
|
|
|
DEFAULT EGOper, /* operation: get, set or clear */
|
|
|
|
charptr TxtPtr) /* if setting, value to set */
|
|
|
|
{
|
|
|
|
char *cp=NULL; /* environment variable name */
|
|
|
|
// char buf[100]; /* enough for envname + 80 char filename */
|
|
|
|
LONG retval; /* -1L on success, 0L on failure */
|
|
|
|
DBGFEN(2,"ZClnEG",NULL);
|
|
|
|
DBGFEX(2,DbgFNm,"0");
|
|
|
|
switch (EGWhat) {
|
|
|
|
case EG_INI: cp = "TEC_INIT"; break;
|
|
|
|
case EG_LIB: cp = "TEC_LIBRARY"; break;
|
|
|
|
case EG_MEM: cp = "TEC_MEMORY"; break;
|
|
|
|
#if VIDEO
|
|
|
|
case EG_VTE: cp = "TEC_VTEDIT"; break;
|
|
|
|
#endif
|
|
|
|
default: return 0L;
|
|
|
|
}
|
|
|
|
if (EGOper == GET_VAL) {
|
|
|
|
if ((cp = getenv(cp)) == NULL) {
|
|
|
|
retval = 0L; /* return failure */
|
|
|
|
} else {
|
|
|
|
retval = -1L; /* success, copy to FBf */
|
|
|
|
strcpy((char*)FBfBeg, cp);
|
|
|
|
FBfPtr = FBfBeg + strlen(cp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Cannot set value */
|
|
|
|
// strcpy(buf, cp); /* build NAME= */
|
|
|
|
// strcat(buf, "=");
|
|
|
|
// if (EGOper == SET_VAL) { /* concatenate new value */
|
|
|
|
// strcat(buf, (char *)TxtPtr);
|
|
|
|
// }
|
|
|
|
// retval = (putenv(buf) != 0) /* if putenv() failed */
|
|
|
|
// ? 0L /* then return failure */
|
|
|
|
// : -1L; /* else return success */
|
|
|
|
retval = 0L;
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
See the definition of MEMMOVE in ZPORT.H for a description of this
|
|
|
|
function.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZCpyBl(Destin, Source, Length)
|
|
|
|
charptr Destin;
|
|
|
|
charptr Source;
|
|
|
|
SIZE_T Length;
|
|
|
|
{
|
|
|
|
if (Source < Destin) {
|
|
|
|
Source += Length;
|
|
|
|
Destin += Length;
|
|
|
|
while (Length-- > 0) {
|
|
|
|
*--Destin = *--Source;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (Length-- > 0) {
|
|
|
|
*Destin++ = *Source++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if DEBUGGING
|
|
|
|
ULONG Zcp2ul(cp) /* convert charptr to ULONG */
|
|
|
|
voidptr cp;
|
|
|
|
{
|
|
|
|
return (ULONG)(cp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
|
|
ZClnUp()
|
|
|
|
This function cleans up in preparation for terminating TECO-C.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZClnUp(VVOID) /* cleanup for TECO-C abort */
|
|
|
|
{
|
|
|
|
DBGFEN(3,"ZClnUp","closing terminal channels and exiting");
|
|
|
|
#if !CURSES
|
|
|
|
if (tty_set == TRUE)
|
|
|
|
#ifdef LINUX
|
|
|
|
tcsetattr(0, TCSANOW, &out);
|
|
|
|
#else
|
|
|
|
ioctl(0, TIOCSETP, &out);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZDoCmd()
|
|
|
|
This function terminates TECO and feeds a command line to the
|
|
|
|
command line interpreter. The command to be executed is passed to this
|
|
|
|
function.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZDoCmd(charptr GBfBeg, charptr GBfPtr) /* die and pass command to OS */
|
|
|
|
{
|
|
|
|
char buf[128+1];
|
|
|
|
char *space_p;
|
|
|
|
DBGFEN(1,"ZDoCmd",NULL);
|
|
|
|
/*
|
|
|
|
* 1. Terminate buf[] and command line in GBf
|
|
|
|
* 2. make local copy since GBf will be free'd in ZClnUp()
|
|
|
|
* 3. separate program name from arguments, if any
|
|
|
|
* 4. Call ZClnUp to free up everything
|
|
|
|
* 5. Execute the command line, with optional arguments. If we know where
|
|
|
|
* the command processor is, use it so we can execute .BAT batch files
|
|
|
|
* 6. we shouldn't be here, exit
|
|
|
|
*/
|
|
|
|
buf[128] = *GBfPtr = '\0';
|
|
|
|
(void)strncpy(buf, (char *)GBfBeg, 128);
|
|
|
|
if ((space_p = strchr(buf,' ')) != NULL) {
|
|
|
|
*space_p++ = '\0';
|
|
|
|
}
|
|
|
|
ZClnUp();
|
|
|
|
execlp ("/bin/sh", "sh", "-c", buf, (space_p) ? space_p : NULL, NULL);
|
|
|
|
/* we should never reach this statement */
|
|
|
|
(void)perror ("");
|
|
|
|
ZExit (EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
#if CURSES
|
|
|
|
static void
|
|
|
|
zaddch(c,wecho)
|
|
|
|
char c;
|
|
|
|
int wecho; /* if set - also do refresh */
|
|
|
|
{
|
|
|
|
static int retflag = 0;
|
|
|
|
int needrefresh = 1;
|
|
|
|
int y,x;
|
|
|
|
if (c=='\n') {
|
|
|
|
if (!retflag) /* previous char was not \r */
|
|
|
|
waddch(curwin,c);
|
|
|
|
else { /* this LF is part of a CRLF sequence */
|
|
|
|
waddch(curwin,'\n'); /* this may force a scroll */
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
}
|
|
|
|
} else if (c=='\b') { /* backspace */
|
|
|
|
getyx(stdscr,y,x);
|
|
|
|
if (x==0 && y>0)
|
|
|
|
move(y-1,HtSize - 1);
|
|
|
|
else if (x>0)
|
|
|
|
move(y,x-1);
|
|
|
|
else /* x==0 and y==0 */
|
|
|
|
;
|
|
|
|
} else { /* c is neither a newline nor a backspace */
|
|
|
|
if (retflag)
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
if (c!='\r') {
|
|
|
|
if (ISSCW) {
|
|
|
|
getyx(stdscr,y,x);
|
|
|
|
if (x < HtSize -1)
|
|
|
|
waddch(curwin,c);
|
|
|
|
} else
|
|
|
|
if (wecho) {
|
|
|
|
#ifdef ULTRIX
|
|
|
|
waddch(curwin,c);
|
|
|
|
#else
|
|
|
|
wechochar(curwin,c);
|
|
|
|
needrefresh = 0;
|
|
|
|
#endif
|
|
|
|
} else
|
|
|
|
waddch(curwin,c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
retflag = (c=='\r');
|
|
|
|
if (wecho && needrefresh)
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
specon()
|
|
|
|
{
|
|
|
|
if (SpcMrk)
|
|
|
|
wattron(stdscr,0400000L * (long) SpcMrk);
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
specoff()
|
|
|
|
{
|
|
|
|
if (SpcMrk)
|
|
|
|
wattroff(stdscr,0400000L * (long) SpcMrk);
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
gr_on()
|
|
|
|
{
|
|
|
|
wattron(stdscr,A_ALTCHARSET);
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
gr_off()
|
|
|
|
{
|
|
|
|
wattroff(stdscr,A_ALTCHARSET);
|
|
|
|
}
|
|
|
|
static int
|
|
|
|
intabs(t)
|
|
|
|
int t;
|
|
|
|
{
|
|
|
|
return (t<0) ? -t : t;
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
zaddch2(c)
|
|
|
|
char c;
|
|
|
|
{
|
|
|
|
static int retflag = 0;
|
|
|
|
if (SeeAll) {
|
|
|
|
if (c=='\n') {
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin, 'e');
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'J');
|
|
|
|
}
|
|
|
|
if (!retflag) { /* previous character was not \r */
|
|
|
|
waddch(curwin,c);
|
|
|
|
} else { /* this LF is in a CRLF sequence */
|
|
|
|
waddch(curwin,'\n');
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
}
|
|
|
|
} else { /* c is not a newline */
|
|
|
|
if (c=='\r') {
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin,'d'); gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'M');
|
|
|
|
}
|
|
|
|
} else if (c=='\t') {
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
int y,x,y1,x1,cntr;
|
|
|
|
getyx(curwin,y,x);
|
|
|
|
waddch(curwin,'\t');
|
|
|
|
getyx(curwin,y1,x1);
|
|
|
|
move(y,x);
|
|
|
|
gr_on();
|
|
|
|
cntr = 0;
|
|
|
|
waddch(curwin,'b');
|
|
|
|
getyx(curwin,y,x);
|
|
|
|
while ((cntr < 8) && (y!=y1 || x!=x1) &&
|
|
|
|
(y<VtSize - winline - ScroLn)) {
|
|
|
|
waddch(curwin,'~');
|
|
|
|
cntr++;
|
|
|
|
getyx(curwin,y,x);
|
|
|
|
}
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT); waddch(curwin,'I');
|
|
|
|
}
|
|
|
|
} else if (c=='\f') {
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin,'c');
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'L');
|
|
|
|
}
|
|
|
|
waddch(curwin,'\n');
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
} else if (c==27) {
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin,'{');
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'[');
|
|
|
|
}
|
|
|
|
} else if (c==VRTTAB) { /* Vertical tab */
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin,'i');
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'K');
|
|
|
|
}
|
|
|
|
waddch(curwin,'\n');
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
} else if (c=='\b') {
|
|
|
|
waddch(curwin,CT);
|
|
|
|
waddch(curwin,'H');
|
|
|
|
} else if (c & 0200) {
|
|
|
|
int i;
|
|
|
|
char a,b;
|
|
|
|
waddch(curwin,LB);
|
|
|
|
c = c & 0177;
|
|
|
|
i = c/16;
|
|
|
|
if (i==0)
|
|
|
|
a='8';
|
|
|
|
else if (i==1)
|
|
|
|
a='9';
|
|
|
|
else
|
|
|
|
a = i - 2 + 'A';
|
|
|
|
i = (c % 16);
|
|
|
|
b = (i > 9) ? (i - 10 + 'A') : (i + '0');
|
|
|
|
waddch(curwin,a);
|
|
|
|
waddch(curwin,b);
|
|
|
|
waddch(curwin,RB);
|
|
|
|
} else if (c < 32) {
|
|
|
|
waddch(curwin, CT);
|
|
|
|
waddch(curwin, c | 64);
|
|
|
|
} else
|
|
|
|
waddch(curwin,c);
|
|
|
|
}
|
|
|
|
retflag = (c==CRETRN);
|
|
|
|
} else { /* not in SEEALL mode */
|
|
|
|
c = c & 0177; /* dump 8th bit */
|
|
|
|
if (c=='\n') {
|
|
|
|
waddch(curwin,'\n');
|
|
|
|
waddch(curwin,'\r');
|
|
|
|
} else if (c=='\b') {
|
|
|
|
waddch(curwin,'^');
|
|
|
|
waddch(curwin,'H');
|
|
|
|
} else { /* c is neither a newline nor a backspace */
|
|
|
|
switch (c) {
|
|
|
|
case CRETRN:
|
|
|
|
if (EzFlag & EZ_INVCR) {
|
|
|
|
waddch(curwin, ' ');
|
|
|
|
} else if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin, 'd');
|
|
|
|
gr_off();
|
|
|
|
} else if (EzFlag & EZ_ARROW) {
|
|
|
|
specon();
|
|
|
|
waddch(curwin, ACS_LARROW);
|
|
|
|
specoff();
|
|
|
|
} else {
|
|
|
|
specon();
|
|
|
|
waddch(curwin,'`');
|
|
|
|
specoff();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ESCAPE:
|
|
|
|
specon();
|
|
|
|
waddch(curwin,'$');
|
|
|
|
specoff();
|
|
|
|
break;
|
|
|
|
case VRTTAB:
|
|
|
|
case FORMFD:
|
|
|
|
if (EzFlag & EZ_VT100GRAPHICS) {
|
|
|
|
gr_on();
|
|
|
|
waddch(curwin,c);
|
|
|
|
gr_off();
|
|
|
|
} else {
|
|
|
|
waddch(curwin, c);
|
|
|
|
}
|
|
|
|
waddch(curwin, '\n');
|
|
|
|
waddch(curwin, '\r');
|
|
|
|
default:
|
|
|
|
waddch(curwin,c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
retflag = (c=='\r');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
|
|
ZDspBf()
|
|
|
|
This function displays a buffer of a given length on the terminal
|
|
|
|
screen. On the VAX (and maybe other systems) doing any kind of output
|
|
|
|
involves a fair amount of overhead, regardless of the size of the buffer
|
|
|
|
being output. It is therefore better to make a single call to the operating
|
|
|
|
system's output function than to call the function for each and every
|
|
|
|
character. If such improvements do not apply to the system this program
|
|
|
|
is running on, then this function can simply call ZDspCh for every character
|
|
|
|
in the buffer.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZDspBf(buffer, length) /* output a buffer to terminal */
|
|
|
|
charptr buffer;
|
|
|
|
SIZE_T length;
|
|
|
|
{
|
|
|
|
#if CURSES
|
|
|
|
int i;
|
|
|
|
int y,x;
|
|
|
|
for (i=0;i<length;i++) {
|
|
|
|
if (ISSCW) {
|
|
|
|
getyx(stdscr,y,x);
|
|
|
|
if (x>=(HtSize-1))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!GotCtC)
|
|
|
|
zaddch(*(buffer+i),0);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wrefresh(curwin);
|
|
|
|
#else
|
|
|
|
if (write(fileno(stdout), buffer, length) == -1) {
|
|
|
|
puts("Unable to write to terminal in function ZDspBf");
|
|
|
|
TAbort(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZDspCh()
|
|
|
|
This function outputs a single character to the terminal.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZDspCh(Charac) /* output a character to terminal */
|
|
|
|
char Charac;
|
|
|
|
{
|
|
|
|
#if CURSES
|
|
|
|
zaddch(Charac,1);
|
|
|
|
#else
|
|
|
|
if (write(fileno(stdout), &Charac, 1) == -1) {
|
|
|
|
puts("Unable to write to terminal in function ZDspCh");
|
|
|
|
TAbort(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZExCtB()
|
|
|
|
This function implements the TECO ^B command, which returns the
|
|
|
|
current date encoded in the following way:
|
|
|
|
((year-1900)*16+month)*32+day
|
|
|
|
*****************************************************************************/
|
|
|
|
DEFAULT ZExCtB() /* return current date */
|
|
|
|
{
|
|
|
|
time_t clockt;
|
|
|
|
struct tm *time_of_day;
|
|
|
|
int tecodate;
|
|
|
|
DBGFEN(1,"ZExCtB","");
|
|
|
|
clockt=time(NULL);
|
|
|
|
time_of_day=localtime(&clockt);
|
|
|
|
tecodate = ((time_of_day->tm_year)*16+time_of_day->tm_mon+1)*32
|
|
|
|
+ time_of_day->tm_mday ;
|
|
|
|
DBGFEX(1,DbgFNm,"PushEx()");
|
|
|
|
return PushEx(tecodate, OPERAND);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZExCtH()
|
|
|
|
This function implements the TECO ^H command, which returns the
|
|
|
|
current time encoded in the following way:
|
|
|
|
(seconds since midnight) / 2
|
|
|
|
*****************************************************************************/
|
|
|
|
DEFAULT ZExCtH() /* return current time */
|
|
|
|
{
|
|
|
|
time_t clockt;
|
|
|
|
struct tm *time_of_day;
|
|
|
|
int tecotime;
|
|
|
|
DBGFEN(1,"ZExCtH","");
|
|
|
|
clockt=time(NULL);
|
|
|
|
time_of_day=localtime(&clockt);
|
|
|
|
tecotime = time_of_day->tm_hour * 60 /* hours * 60 */;
|
|
|
|
tecotime += time_of_day->tm_min; /* minutes */
|
|
|
|
tecotime *= 30;
|
|
|
|
tecotime += time_of_day->tm_sec >> 1; /* seconds / 2 */
|
|
|
|
DBGFEX(1,DbgFNm,"PushEx()");
|
|
|
|
return PushEx(tecotime, OPERAND);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZExeEJ()
|
|
|
|
This function executes an EJ command, which returns environment
|
|
|
|
characteristics. It returns:
|
|
|
|
-1EJ 1024 under VAX/VMS (4*256 = VAX, 0 = VMS in native mode)
|
|
|
|
1025 under Ultrix (4*256 = VAX, 1 = Ultrix)
|
|
|
|
25600 under Sun/SunOS (100*256 = Sun, 0 = SunOS)
|
|
|
|
25856 under MS-DOS (101*256 = IBM-PC, 0 = MS-DOS)
|
|
|
|
25857 under OS/2 (101*256 = IBM-PC, 1 = OS/2)
|
|
|
|
25858 under Linux (101*256 = IBM-PC, 2 = Linux)
|
|
|
|
0EJ process id on VAXen or Unix/Linux, 0 on anything else
|
|
|
|
1EJ 0 on all systems
|
|
|
|
2EJ UIC, in longword format (unlike TECO-11) on VAX/VMS,
|
|
|
|
0 on all other systems.
|
|
|
|
*****************************************************************************/
|
|
|
|
DEFAULT ZExeEJ() /* execute an EJ command */
|
|
|
|
{
|
|
|
|
DBGFEN(1,"ZExeEJ",NULL);
|
|
|
|
if (EStTop == EStBot) { /* if no numeric argument */
|
|
|
|
NArgmt = 0; /* default is 0EJ */
|
|
|
|
} else {
|
|
|
|
UMinus(); /* if -EJ, make it -1EJ */
|
|
|
|
if (GetNmA() == FAILURE) { /* get numeric argument */
|
|
|
|
DBGFEX(1,DbgFNm,"FAILURE");
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NArgmt == -1) {
|
|
|
|
DBGFEX(1,DbgFNm,"PushEx(25858)");
|
|
|
|
return PushEx((LONG)25858, OPERAND); /* means "PC Linux" */
|
|
|
|
}
|
|
|
|
if (NArgmt == 0) {
|
|
|
|
DBGFEX(1,DbgFNm,"PushEx(getppid())");
|
|
|
|
return PushEx((LONG)getppid(), OPERAND);
|
|
|
|
}
|
|
|
|
DBGFEX(1,DbgFNm,"ExeNYI()");
|
|
|
|
return ExeNYI();
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZExit()
|
|
|
|
This function terminates TECO-C with a status value.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZExit(estat) /* terminate TECO-C */
|
|
|
|
DEFAULT estat;
|
|
|
|
{
|
|
|
|
#if CURSES
|
|
|
|
nodelay(stdscr,FALSE); /* to avoid a bug in some System V.2 */
|
|
|
|
/* releases of curses */
|
|
|
|
endwin();
|
|
|
|
#endif
|
|
|
|
ZClnUp();
|
|
|
|
exit(estat);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZFree()
|
|
|
|
This function frees memory previously allocated by the ZAlloc
|
|
|
|
function.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZFree(pointer) /* free memory allocated by ZAlloc */
|
|
|
|
voidptr pointer;
|
|
|
|
{
|
|
|
|
free(pointer);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZHelp()
|
|
|
|
This function accepts a help string and displays the corresponding
|
|
|
|
help text.
|
|
|
|
it should be control-C interrupt-able.
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZHelp(HlpBeg, HlpEnd, SysLib, Prompt)
|
|
|
|
charptr HlpBeg; /* first char of help request */
|
|
|
|
charptr HlpEnd; /* last character of help request */
|
|
|
|
BOOLEAN SysLib; /* use default HELP library? */
|
|
|
|
BOOLEAN Prompt; /* enter interactive help mode? */
|
|
|
|
{
|
|
|
|
(void)ExeNYI();
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZIClos()
|
|
|
|
This function closes the current input file. It must
|
|
|
|
1. if current input stream is not open, simply return
|
|
|
|
2. close the input file
|
|
|
|
3. set open indicator to FALSE
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZIClos(IfIndx) /* close input file */
|
|
|
|
DEFAULT IfIndx; /* index into IFiles array */
|
|
|
|
{
|
|
|
|
DBGFEN(2,"ZIClos",NULL);
|
|
|
|
if (IsOpnI[IfIndx]) { /* if it's open */
|
|
|
|
if (fclose(IFiles[IfIndx]) == EOF) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCI);
|
|
|
|
ZExit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
IsOpnI[IfIndx] = FALSE;
|
|
|
|
}
|
|
|
|
DBGFEX(2,DbgFNm,NULL);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZOClDe()
|
|
|
|
This function closes and deletes the current output stream. It must
|
|
|
|
1. if no current output stream is defined, simply return
|
|
|
|
2. close the output stream
|
|
|
|
3. delete the file just closed
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZOClDe(OfIndx) /* close and delete output file */
|
|
|
|
DEFAULT OfIndx; /* index into OFiles array */
|
|
|
|
{
|
|
|
|
DBGFEN(2,"ZOClDe",NULL);
|
|
|
|
if (IsOpnO[OfIndx]) { /* if output stream is open */
|
|
|
|
if (fclose(OFiles[OfIndx].OStrem) == EOF) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrStr(ERR_UCO, OFiles[OfIndx].OFNam);
|
|
|
|
ZExit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (remove(OFiles[OfIndx].OFNam) != 0) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrStr(ERR_UCD, OFiles[OfIndx].OFNam);
|
|
|
|
ZExit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
IsOpnO[OfIndx] = FALSE;
|
|
|
|
}
|
|
|
|
DBGFEX(2,DbgFNm,NULL);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZOClos()
|
|
|
|
This function closes the current output stream. It is only called
|
|
|
|
when an output stream is defined. It must
|
|
|
|
1. flush output to the stream, if neccessary
|
|
|
|
2. close the stream
|
|
|
|
3. set OFile to -1
|
|
|
|
*****************************************************************************/
|
|
|
|
VVOID ZOClos(OfIndx) /* close output file */
|
|
|
|
DEFAULT OfIndx; /* index into OFiles array */
|
|
|
|
{
|
|
|
|
int ver;
|
|
|
|
char TmpFsp[FILENAME_MAX];
|
|
|
|
char move_err[1024];
|
|
|
|
DBGFEN(2,"ZOClos",NULL);
|
|
|
|
if (!IsOpnO[OfIndx]) { /* if it's not open */
|
|
|
|
DBGFEX(2,DbgFNm,NULL);
|
|
|
|
return; /* we're done */
|
|
|
|
}
|
|
|
|
if (fclose(OFiles[OfIndx].OStrem) == EOF) { /* close it */
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO); /* unable to close */
|
|
|
|
ZExit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (OFiles[OfIndx].OTNam[0] != '\0') { /* if temporary output file */
|
|
|
|
if (OFiles[OfIndx].forBackup) {
|
|
|
|
(void)strcpy(TmpFsp, OFiles[OfIndx].OTNam);/* copy to TmpFsp */
|
|
|
|
if ((EzFlag&EZ_NO_STRIP)==0) {
|
|
|
|
char *DotPtr = strchr(TmpFsp, '.'); /* find the "." */
|
|
|
|
if (DotPtr != NULL) { /* if "." exists */
|
|
|
|
*DotPtr = '\0'; /* make it null */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (EzFlag&EZ_NO_VER) {
|
|
|
|
(void)strcat(TmpFsp, ".bak"); /* append ".bak" */
|
|
|
|
if (access(TmpFsp, 0) == 0) { /* old "x.bak"? */
|
|
|
|
#if DEBUGGING
|
|
|
|
sprintf(DbgSBf,
|
|
|
|
"deleting old version of %s\r\n",
|
|
|
|
TmpFsp);
|
|
|
|
DbgFMs(2,DbgFNm,DbgSBf);
|
|
|
|
#endif
|
|
|
|
if (remove(TmpFsp) != 0) { /* delete it */
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO);
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ver = vernum(TmpFsp);
|
|
|
|
if (ver==(-3)) {
|
|
|
|
puts("\nWARNING: Versioning disabled\n");
|
|
|
|
(void)strcat(TmpFsp, ".bak"); /* append ".bak" */
|
|
|
|
if (access(TmpFsp, 0) == 0) { /* old "x.bak"? */
|
|
|
|
#if DEBUGGING
|
|
|
|
sprintf(DbgSBf,
|
|
|
|
"deleting old version of %s\r\n",
|
|
|
|
TmpFsp);
|
|
|
|
DbgFMs(2,DbgFNm,DbgSBf);
|
|
|
|
#endif
|
|
|
|
if (remove(TmpFsp) != 0) { /* delete it */
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO);
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (ver==(-2) || ver==0) {
|
|
|
|
(void)strcat(TmpFsp, ";1");
|
|
|
|
} else if (ver==(-1)) { /* can't read dir */
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO); /* una to close o */
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
} else { /* ver > 0 */
|
|
|
|
int ln = strlen(TmpFsp);
|
|
|
|
ver++;
|
|
|
|
strcat(TmpFsp, ";");
|
|
|
|
MakDBf((LONG)ver, 10);
|
|
|
|
strncat(TmpFsp, (char *)DBfBeg, DBfPtr-DBfBeg);
|
|
|
|
*(TmpFsp+ln+(1+DBfPtr-DBfBeg)+1) = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if DEBUGGING
|
|
|
|
sprintf(DbgSBf,"renaming %s to %s\r\n",
|
|
|
|
OFiles[OfIndx].OTNam, TmpFsp);
|
|
|
|
DbgFMs(2,DbgFNm,DbgSBf);
|
|
|
|
#endif
|
|
|
|
if (rename(OFiles[OfIndx].OTNam, TmpFsp)) { /* TAA changed to use rename */
|
|
|
|
ZErMsg();
|
|
|
|
ZDspBf((unsigned char *)"Edit saved in ", 14);
|
|
|
|
ZDspBf(OFiles[OfIndx].OFNam,
|
|
|
|
strlen(OFiles[OfIndx].OFNam));
|
|
|
|
ErrMsg(ERR_UCO);
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else { /* Delete original if not backing up */
|
|
|
|
if (remove(OFiles[OfIndx].OTNam) != 0) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO);
|
|
|
|
DBGFEX(2,DbgFNm,"remove() failed");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if DEBUGGING
|
|
|
|
sprintf(DbgSBf,"renaming %s to %s\r\n",
|
|
|
|
OFiles[OfIndx].OFNam, OFiles[OfIndx].OTNam);
|
|
|
|
DbgFMs(2,DbgFNm,DbgSBf);
|
|
|
|
#endif
|
|
|
|
if (rename(OFiles[OfIndx].OFNam,
|
|
|
|
OFiles[OfIndx].OTNam)) {
|
|
|
|
ZErMsg();
|
|
|
|
ErrMsg(ERR_UCO);
|
|
|
|
ZClnUp();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
IsOpnO[OfIndx] = FALSE;
|
|
|
|
DBGFEX(2,DbgFNm,NULL);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
ZOpInp()
|
|
|
|
This function opens an input file. The name of the file is pointed
|
|
|
|
to by FBfBeg. FBfPtr points to the character following the last character of
|
|
|
|
the file name.
|
|
|
|
This function is used to open all files, including macro files
|
|
|
|
needed by the "EI" command. The "EIFlag" argument tells this function if
|
|
|
|
it's an "EI" file. If it is, some extra file searching is done to make
|
|
|
|
things convenient for the user. The extra processing is modelled after what
|
|
|
|
happens under VMS (or really, what SHOULD happen under VMS). The basic idea
|
|
|
|
is to find the macro file whether the user has specificed the ".tec" or not,
|
|
|
|
and whether it's in the current directory or the macro library directory.
|
|
|
|
The basic Unix logic is like this:
|
|
|
|
if (the file exists)
|
|
|
|
open it and return SUCCESS
|
|
|
|
if (EIfile) {
|
|
|
|
if (there's no dot and appending ".tec" works)
|
|
|
|
open it and return SUCCESS
|
|
|
|
if (prepending default library directory works)
|
|
|
|
open it and return SUCCESS
|
|
|
|
if (prepending library and appending ".tec" works)
|
|
|
|
open it and return SUCCESS
|
|
|
|
}
|
|
|
|
file not found, so return with error
|
|
|
|
Under VAX/VMS, it's a little different. VMS tries to open the file only
|
|
|
|
twice, each time with the RMS "default type" field set to ".TEC", so VMS
|
|
|
|
will insert ".TEC" if the user doesn't. There's no straightforward way to
|
|
|
|
avoid putting ".TEC" on the end of your TECO macro file namess under VMS,
|
|
|
|
which some would argue is a good thing, as long as you don't have to type
|
|
|
|
the ".TEC" when you use them.
|
|
|
|
Under MS-DOS, the above PDL works, except that when the logic talks about
|
|
|
|
appending ".tec", it doesn't happen if there's alreay a dot in the file
|
|
|
|
name, as you can only have one dot in MS-DOS file names.
|
|
|
|
*****************************************************************************/
|
|
|
|
DEFAULT ZOpInp(IfIndx, EIFile, RepFNF)
|
|
|
|
DEFAULT IfIndx; /* index into file data block array IFiles */
|
|
|
|
BOOLEAN EIFile; /* is it a macro file (hunt for it) */
|
|
|
|
BOOLEAN RepFNF; /* report "file not found" error? */
|
|
|
|
{
|
|
|
|
#if DEBUGGING
|
|
|
|
static char *DbgFNm = "ZOpInp";
|
|
|
|
sprintf(DbgSBf,", FBf = \"%.*s\"", (int)(FBfPtr-FBfBeg), FBfBeg);
|
|
|
|
DbgFEn(2,DbgFNm,DbgSBf);
|
|
|
|
#endif
|
|
|
|
*FBfPtr = '\0'; /* terminate the file name */
|
|
|
|
if ((IFiles[IfIndx] = fopen((char *)FBfBeg, "r")) != NULL) {
|
|
|
|
DBGFEX(1,DbgFNm,"SUCCESS");
|
|
|
|
IFisCR[IfIndx] = 0;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
if (EIFile) {
|
|
|
|
charptr dummyp = NULL;
|
|
|
|
char TmpBfr[FILENAME_MAX];
|
|
|
|
ptrdiff_t TmpLen = FBfPtr-FBfBeg;
|
|
|
|
BOOLEAN noDot;
|
|
|
|
if (noDot = strchr((char *)FBfBeg,'.') == NULL) { /* if no dot */
|
|
|
|
(void)strcat(FBfBeg,".tec"); /* append .tec */
|
|
|
|
FBfPtr += 4;
|
|
|
|
if ((IFiles[IfIndx] = fopen(FBfBeg, "r")) != NULL) {
|
|
|
|
DBGFEX(1,DbgFNm,"SUCCESS");
|
|
|
|
IFisCR[IfIndx] = 0;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MEMMOVE(TmpBfr, FBfBeg, TmpLen); /* save file name */
|
|
|
|
if (ZClnEG(EG_LIB, GET_VAL, dummyp) != -1) { /* get dir spec */
|
|
|
|
goto open_failed;
|
|
|
|
}
|
|
|
|
MEMMOVE(FBfPtr, TmpBfr, TmpLen); /* append name to dir spec */
|
|
|
|
FBfPtr += TmpLen;
|
|
|
|
*FBfPtr = '\0'; /* terminate file name */
|
|
|
|
if ((IFiles[IfIndx] = fopen(FBfBeg, "r")) != NULL) {
|
|
|
|
DBGFEX(1,DbgFNm,"SUCCESS");
|
|
|
|
IFisCR[IfIndx] = 0;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
if (noDot) { /* if no dot */
|
|
|
|
(void)strcat(FBfBeg,".tec"); /* append .tec */
|