home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
the25.zip
/
thesrc251.zip
/
the.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-07-31
|
50KB
|
1,377 lines
/***********************************************************************/
/* THE.C - The Hessling Editor */
/***********************************************************************/
/*
* THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
* Copyright (C) 1991-1997 Mark Hessling
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
*
* The Free Software Foundation, Inc.
* 675 Mass Ave,
* Cambridge, MA 02139 USA.
*
*
* If you make modifications to this software that you feel increases
* it usefulness for the rest of the community, please email the
* changes, enhancements, bug fixes as well as any and all ideas to me.
* This software is going to be maintained and enhanced as deemed
* necessary by the community.
*
* Mark Hessling Email: M.Hessling@qut.edu.au
* PO Box 203 Phone: +617 3802 0800
* Bellara http://www.lightlink.com/hessling/
* QLD 4507 **** Author of THE & Rexx/SQL ****
* Australia ****** Maintainer PDCurses *******
*/
/*
$Id: the.c 2.1 1995/06/24 16:31:24 MH Rel MH $
*/
#define MAIN 1
#include <the.h>
#include <proto.h>
#if defined(DOS) || defined(OS2)
# if !defined(EMX) && !defined(GO32)
# include <direct.h>
# endif
#endif
#ifdef HAVE_PROTO
static RETSIGTYPE handle_signal(int);
static void display_info(CHARTYPE *);
static void init_signals(void);
#else
static RETSIGTYPE handle_signal();
static void display_info();
static void init_signals();
#endif
/*--------------------------- global data -----------------------------*/
WINDOW *statarea=NULL,*error_window=NULL,*divider=NULL;
VIEW_DETAILS *vd_current=(VIEW_DETAILS *)NULL;
VIEW_DETAILS *vd_first=(VIEW_DETAILS *)NULL;
VIEW_DETAILS *vd_last=(VIEW_DETAILS *)NULL;
VIEW_DETAILS *vd_mark=(VIEW_DETAILS *)NULL;
CHARTYPE number_of_views = 0; /* number of views */
CHARTYPE number_of_files = 0; /* number of files */
CHARTYPE display_screens = 1; /* number of screens */
CHARTYPE current_screen = 0;
SCREEN_DETAILS screen[MAX_SCREENS]; /* 2 screen structures */
bool rexx_support; /* initially REXX support */
bool batch_only=FALSE; /* are we running in batch ? */
bool horizontal=TRUE;
bool first_screen_display=FALSE;
short save_coord_x[VIEW_WINDOWS];
short save_coord_y[VIEW_WINDOWS];
LINE *next_line=NULL,*curr_line=NULL;
LINE *first_file_name=NULL,*current_file_name=NULL;
LINE *editv=NULL;
bool error_on_screen=FALSE;
bool colour_support=TRUE; /* indicates if colour is supported */
bool initial=TRUE;
bool been_interactive=FALSE;
CHARTYPE *rec=NULL;
LENGTHTYPE rec_len = 0; /* length of rec */
CHARTYPE *trec=NULL;
LENGTHTYPE trec_len = 0;
CHARTYPE *cmd_rec=NULL;
unsigned short cmd_rec_len = 0; /* length of cmd_rec */
CHARTYPE *pre_rec=NULL;
unsigned short pre_rec_len = 0; /* length of cmd_rec */
CHARTYPE *profile_command_line=NULL;
CHARTYPE *target_buffer=NULL; /* used in get_item_values() */
unsigned short target_buffer_len=0; /* length of target buffer */
bool focus_changed = FALSE; /* indicates if focus line has changed */
bool current_changed = FALSE;/* indicates if current line has changed */
bool in_profile=FALSE; /* indicates if processing profile */
bool in_nomsg=FALSE; /* indicates if running from NOMSG command */
bool in_reprofile=FALSE; /* indicates if reprocessing profile */
int profile_file_executions=0; /* number of times profile file has executed */
bool execute_profile=TRUE;/* indicates if we are to process a profile */
bool in_macro=FALSE; /* indicates if processing REXX macro */
bool in_repeat=FALSE; /* indicates if running REPEAT command */
bool in_readv=FALSE; /* indicates if processing READV CMDLINE */
bool file_read=FALSE; /* indicates if we have read the file */
bool curses_started=FALSE; /* indicates if curses has started */
bool readonly=FALSE; /* indicates if running THE in readonly mode */
CHARTYPE *the_version = (CHARTYPE *)"2.5.1";
CHARTYPE *the_release = (CHARTYPE *)"28-Jul-1998";
CHARTYPE *the_copyright = (CHARTYPE *)"Copyright 1991-1998 Mark Hessling";
CHARTYPE term_name[20]; /* $TERM value */
CHARTYPE *tempfilename = (CHARTYPE *)NULL;
#if defined(UNIX)
CHARTYPE user_home_dir[MAX_FILE_NAME+1];
# define THE_PROFILE_FILE ".therc"
#else
# define THE_PROFILE_FILE "PROFILE.THE"
#endif
#if !defined(MULTIPLE_PSEUDO_FILES)
CHARTYPE *rexxoutname = (CHARTYPE *)"REXX.$$$";
CHARTYPE *keyfilename = (CHARTYPE *)"KEY$$$.$$$";
CHARTYPE rexx_pathname[MAX_FILE_NAME+1];
CHARTYPE rexx_filename[10];
# ifdef VMS
CHARTYPE *dirfilename = (CHARTYPE *)"DIR.THE";
# else
CHARTYPE *dirfilename = (CHARTYPE *)"DIR.DIR";
# endif
#endif
#ifndef XCURSES
# define XTERM_PROGRAM "N/A"
#endif
CHARTYPE xterm_program[MAX_FILE_NAME+1]; /* default shell for XCURSES */
CHARTYPE macro_suffix[12] = ".the"; /* default extension for macros */
#if !defined(MULTIPLE_PSEUDO_FILES)
CHARTYPE dir_pathname[MAX_FILE_NAME+1];
CHARTYPE dir_filename[10];
CHARTYPE key_pathname[MAX_FILE_NAME+1];
CHARTYPE key_filename[15];
#endif
CHARTYPE curr_path[MAX_FILE_NAME+1];
CHARTYPE sp_path[MAX_FILE_NAME+1];
CHARTYPE sp_fname[MAX_FILE_NAME+1];
CHARTYPE dir_path[MAX_FILE_NAME+1]; /* for dir and ls commands */
CHARTYPE dir_files[MAX_FILE_NAME+1]; /* for dir and ls commands */
CHARTYPE rexx_macro_name[MAX_FILE_NAME+1]; /* current rexx macro name */
CHARTYPE rexx_macro_parameters[MAX_FILE_NAME+1]; /* current rexx macro parameters */
CHARTYPE the_home_dir[MAX_FILE_NAME+1];
CHARTYPE the_help_file[MAX_FILE_NAME+1];
CHARTYPE the_macro_path[MAX_FILE_NAME+1];
CHARTYPE the_macro_path_buf[MAX_FILE_NAME+1];
CHARTYPE *the_macro_dir[MAX_MACRO_DIRS];
int max_macro_dirs = 0;
CHARTYPE *prf_arg=(CHARTYPE *)NULL;
CHARTYPE *local_prf=(CHARTYPE *)NULL;
CHARTYPE *specified_prf=(CHARTYPE *)NULL;
CHARTYPE tabkey_insert='C';
CHARTYPE tabkey_overwrite='T';
unsigned short file_start = 38;
#if defined(UNIX) || defined(OS2) || defined(EMX)
CHARTYPE *spooler_name=NULL;
#endif
struct stat stat_buf;
LENGTHTYPE display_length=0;
short lastrc=0;
short compatible_look=COMPAT_THE;
short compatible_feel=COMPAT_THE;
short compatible_keys=COMPAT_THE;
short prefix_width=DEFAULT_PREFIX_WIDTH;
short prefix_gap=DEFAULT_PREFIX_GAP;
chtype etmode_table[256];
bool etmode_flag[256];
#define DEFAULT_LINES 24
#define DEFAULT_COLS 80
short terminal_lines=DEFAULT_LINES;
short terminal_cols=DEFAULT_COLS;
/*---------------------------------------------------------------------*/
/* Following are for getopt function(s). */
/*---------------------------------------------------------------------*/
extern char *optarg;
extern int optind;
/*---------------------------------------------------------------------*/
/* Following are for original cursor position for EXTRACT /CURSOR/ */
/*---------------------------------------------------------------------*/
LINETYPE original_screen_line = (-1L);
LINETYPE original_screen_column = (-1L);
LINETYPE original_file_line = (-1L);
LINETYPE original_file_column = (-1L);
/*---------------------------------------------------------------------*/
/* Following are for startup LINE and COLUMN */
/*---------------------------------------------------------------------*/
LINETYPE startup_line = 0L;
LENGTHTYPE startup_column = 0;
#ifdef XCURSES
char *XCursesProgramName = "the";
#endif
/***********************************************************************/
#ifdef MSWIN
int Themain(argc,argv)
int argc;
char *argv[];
#else
#ifdef HAVE_PROTO
int main(int argc, char *argv[])
#else
int main(argc,argv)
short argc;
char *argv[];
#endif
#endif
/***********************************************************************/
{
/*-------------------------- external data ----------------------------*/
extern CHARTYPE *last_message;
extern DEFINE *first_define;
extern DEFINE *first_mouse_define;
extern bool CLEARSCREENx;
extern LINE *first_prefix_synonym;
extern CHARTYPE last_change_command[MAX_COMMAND_LENGTH];
extern CHARTYPE last_target[MAX_COMMAND_LENGTH];
extern bool SLKx;
extern bool SBx;
#ifdef MSWIN
extern void efree();
extern char far *emalloc(unsigned long);
extern char far *erealloc(void far *,unsigned long);
extern char far *ecalloc();
#endif
/*--------------------------- local data ------------------------------*/
register short i=0;
short c=0;
bool trap_signals=TRUE;
bool pause_for_errors=FALSE;
short rc=RC_OK;
char *envptr=NULL,*tmpptr=NULL;
/*--------------------------- processing ------------------------------*/
#ifdef __EMX__
_wildcard(&argc,&argv);
#endif
#ifdef TRACE
trace_initialise();
trace_function("the.c: main");
#endif
/*---------------------------------------------------------------------*/
/* Ensure that CURRENT_VIEW is NULL before starting. This is to ensure */
/* that any errors generated before CURRENT_VIEW is assigned are */
/* handled gracefully. */
/*---------------------------------------------------------------------*/
CURRENT_VIEW = (VIEW_DETAILS *)NULL;
/*---------------------------------------------------------------------*/
/* Set up our memory management calls. This is where you can specify a */
/* debugging memory manager. */
/*---------------------------------------------------------------------*/
#ifdef MSWIN
the_malloc = emalloc;
the_calloc = ecalloc;
the_free = efree;
the_realloc = erealloc;
Win31Startup();
#else
if (getenv("NO_FLISTS"))
{
the_malloc = malloc;
the_calloc = calloc;
the_free = free;
the_realloc = realloc;
}
else
{
the_malloc = get_a_block;
the_calloc = NULL;
the_free = give_a_block;
the_realloc = resize_a_block;
init_memory_table();
}
#endif
/*---------------------------------------------------------------------*/
/* Set up flag to indicate that we are not interactive...yet. */
/*---------------------------------------------------------------------*/
in_profile = TRUE;
execute_profile = TRUE;
in_macro = FALSE;
/*---------------------------------------------------------------------*/
/* Initialise the printer spooler. */
/*---------------------------------------------------------------------*/
#if defined(UNIX) || defined(OS2) || defined(EMX)
if ((spooler_name = (CHARTYPE *)(*the_malloc)(5*sizeof(CHARTYPE))) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(1);
}
# ifdef UNIX
strcpy((DEFCHAR *)spooler_name,(DEFCHAR *)"lpr");
# else
strcpy((DEFCHAR *)spooler_name,(DEFCHAR *)"LPT1");
# endif
#endif
/*---------------------------------------------------------------------*/
/* Get all environment variables here. Some may be overridden by */
/* command-line switches. (future possibility) */
/*---------------------------------------------------------------------*/
#if defined(UNIX)
if ((envptr = getenv("HOME")) != NULL)
strcpy((DEFCHAR *)user_home_dir,envptr);
else
strcpy((DEFCHAR *)user_home_dir,"./");
if (*(user_home_dir+strlen((DEFCHAR *)user_home_dir)-1) != ISLASH)
strcat((DEFCHAR *)user_home_dir,(DEFCHAR *)ISTR_SLASH);
if ((envptr = getenv("TERM")) != NULL)
strcpy((DEFCHAR *)term_name,envptr);
else
strcpy((DEFCHAR *)term_name,"default");
#endif
#if defined(__EMX__)
if (_osmode == DOS_MODE)
strcpy((DEFCHAR *)term_name,"DOS");
else
strcpy((DEFCHAR *)term_name,"OS2");
#elif defined(DOS)
strcpy((DEFCHAR *)term_name,"DOS");
#elif defined(OS2)
strcpy((DEFCHAR *)term_name,"OS2");
#elif defined(XCURSES)
strcpy((DEFCHAR *)term_name,"X11");
#elif defined(WIN32)
strcpy((DEFCHAR *)term_name,"WIN32");
#endif
strcpy((DEFCHAR *)xterm_program,XTERM_PROGRAM);
/*---------------------------------------------------------------------*/
/* Get THE_HOME_DIR first (as all other paths rely on this value) */
/*---------------------------------------------------------------------*/
if ((envptr = getenv("THE_HOME_DIR")) != NULL)
{
strcpy((DEFCHAR *)the_home_dir,envptr);
(void *)strrmdup(strtrans(the_home_dir,OSLASH,ISLASH),ISLASH);
if ((the_home_dir[strlen((DEFCHAR *)the_home_dir)-1]) != ISLASH)
strcat((DEFCHAR *)the_home_dir,(DEFCHAR *)ISTR_SLASH);
}
else
{
#if defined(UNIX)
strcpy((DEFCHAR *)the_home_dir,(DEFCHAR *)THE_HOME_DIRECTORY);
#else
strcpy((DEFCHAR *)the_home_dir,(DEFCHAR *)argv[0]);
(void *)strrmdup(strtrans(the_home_dir,OSLASH,ISLASH),ISLASH);
i = strzreveq(the_home_dir,ISLASH);
if (i != (-1))
the_home_dir[i+1] = '\0';
else
the_home_dir[0] = '\0';
#endif
}
/*---------------------------------------------------------------------*/
/* Get THE_MACRO_PATH environment variable. If not set set up default */
/* to be THE_HOME_DIR followed by the current directory. */
/*---------------------------------------------------------------------*/
if ((envptr = getenv("THE_MACRO_PATH")) != NULL)
Macropath((CHARTYPE*)envptr);
else
{
strcpy((DEFCHAR *)the_macro_path,(DEFCHAR *)the_home_dir);
if (strcmp((DEFCHAR *)the_macro_path,"") == 0)
strcpy((DEFCHAR *)the_macro_path,".");
#if defined(UNIX)
strcat((DEFCHAR *)the_macro_path,":.");
#else
strcat((DEFCHAR *)the_macro_path,";.");
#endif
Macropath(the_macro_path);
}
/*---------------------------------------------------------------------*/
/* Set up help file name. */
/*---------------------------------------------------------------------*/
if ((envptr = getenv("THE_HELP_FILE")) != NULL)
strcpy((DEFCHAR *)the_help_file,envptr);
else
{
strcpy((DEFCHAR *)the_help_file,(DEFCHAR *)the_home_dir);
/* strcat((DEFCHAR *)the_help_file,(DEFCHAR *)term_name); */
strcat((DEFCHAR *)the_help_file,"THE_Help.txt");
}
(void *)strrmdup(strtrans(the_help_file,OSLASH,ISLASH),ISLASH);
/*---------------------------------------------------------------------*/
/* Process the command line arguments. */
/*---------------------------------------------------------------------*/
while ((c = getopt(argc,argv,"ksSbmnrl:c:p:w:a:u:h?")) != EOF)
switch((char)c)
{
case 's': /* don't trap signals */
trap_signals = FALSE;
break;
case 'k': /* allow Soft Label Keys */
SLKx = TRUE;
break;
case 'S': /* allow scrollbar */
SBx = TRUE;
break;
case 'l': /* set current line on startup */
startup_line = (LINETYPE)atol(optarg);
if (startup_line < 0L)
{
cleanup();
display_error(5,(CHARTYPE *)"startup line MUST be > 0",FALSE);
return(4);
}
break;
case 'c': /* set current column on startup */
startup_column = (LENGTHTYPE)atoi(optarg);
if (startup_column == 0)
{
cleanup();
display_error(5,(CHARTYPE *)"startup column MUST be > 0",FALSE);
return(4);
}
break;
case 'b': /* batch processing */
batch_only = TRUE;
break;
case 'm': /* force into MONO */
colour_support = FALSE;
break;
case 'n': /* do not execute any profile file */
execute_profile = FALSE;
break;
case 'r': /* run in readonly mode */
readonly = TRUE;
break;
case 'p': /* profile file name */
if ((specified_prf = (CHARTYPE *)(*the_malloc)((strlen(optarg)+1)*sizeof(CHARTYPE))) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(2);
}
strcpy((DEFCHAR *)specified_prf,(DEFCHAR *)optarg);
break;
case 'a': /* profile arguments */
if ((prf_arg = (CHARTYPE *)(*the_malloc)((strlen(optarg)+1)*sizeof(CHARTYPE))) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(3);
}
strcpy((DEFCHAR *)prf_arg,(DEFCHAR *)optarg);
break;
case 'w': /* width of line */
max_line_length = (unsigned short)atoi(optarg);
if (max_line_length < 10)
{
cleanup();
display_error(5,(CHARTYPE *)"- width MUST be >= 10",FALSE);
return(4);
}
if (max_line_length > 32700)
{
cleanup();
display_error(6,(CHARTYPE *)"- width MUST be <= 32700",FALSE);
return(5);
}
break;
case 'u': /* display length */
display_length = (unsigned short)atoi(optarg);
if (display_length == 0)
{
cleanup();
display_error(5,(CHARTYPE *)"- display length MUST be > 0",FALSE);
return(4);
}
break;
case 'h':
case '?':
cleanup();
display_info((CHARTYPE *)argv[0]);
return(0);
break;
default:
break;
}
if (optind<argc)
{
while(optind<argc)
{
if ((current_file_name = add_line(first_file_name,
current_file_name,
strrmdup(strtrans((CHARTYPE *)argv[optind],OSLASH,ISLASH),ISLASH),
strlen(argv[optind]),0,TRUE)) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(6);
}
if (first_file_name == NULL)
first_file_name = current_file_name;
optind++;
}
}
else
{
#if defined(MSWIN)
return(1);
#else
if ((current_file_name = add_line(first_file_name,
current_file_name,
CURRENT_DIR,
strlen((DEFCHAR *)CURRENT_DIR),0,TRUE)) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(7);
}
if (first_file_name == NULL)
first_file_name = current_file_name;
#endif
}
/*---------------------------------------------------------------------*/
/* Check any command line conflicts... */
/*---------------------------------------------------------------------*/
if (display_length > 0
&& display_length > max_line_length)
{
cleanup();
display_error(6,(CHARTYPE *)"- width MUST be >= display length",FALSE);
return(8);
}
/*---------------------------------------------------------------------*/
/* Override any default paths,filenames etc if supplied on command line*/
/*---------------------------------------------------------------------*/
if (setup_profile_files(specified_prf) != RC_OK)
{
cleanup();
return(8);
}
if (specified_prf != NULL)
(*the_free)(specified_prf);
/*---------------------------------------------------------------------*/
/* Allocate some memory to working variables... */
/*---------------------------------------------------------------------*/
rc = allocate_working_memory();
if (rc)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(rc);
}
/*---------------------------------------------------------------------*/
/* Allocate memory to pre_rec and set it to blanks. */
/*---------------------------------------------------------------------*/
if ((pre_rec = (CHARTYPE *)(*the_malloc)((MAX_PREFIX_WIDTH+1)*sizeof(CHARTYPE))) == NULL)
{
cleanup();
display_error(30,(CHARTYPE *)"",FALSE);
return(16);
}
memset(pre_rec,' ',MAX_PREFIX_WIDTH+1);
pre_rec_len = 0;
/*---------------------------------------------------------------------*/
/* Set up saved command buffers to empty... */
/*---------------------------------------------------------------------*/
strcpy((DEFCHAR *)last_target,"");
strcpy((DEFCHAR *)last_change_command,"");
/*---------------------------------------------------------------------*/
/* Determine the current working directory. */
/* Do this before any other file setting up so that we don't change the*/
/* current directory from the default. */
/*---------------------------------------------------------------------*/
#if defined(EMX)
_getcwd2(curr_path,MAX_FILE_NAME);
#else
getcwd((DEFCHAR *)curr_path,MAX_FILE_NAME);
#endif
#if !defined(MULTIPLE_PSEUDO_FILES)
/*---------------------------------------------------------------------*/
/* Set up filename for directory temporary file (DIR.DIR). */
/* Set up filename for REXX capture file (REXX.$$$). */
/*---------------------------------------------------------------------*/
#ifdef UNIX
strcpy((DEFCHAR *)dir_pathname,(DEFCHAR *)user_home_dir);
#endif
#if defined(DOS) || defined(OS2) || defined(WIN32)
strcpy((DEFCHAR *)dir_pathname,(DEFCHAR *)ISTR_SLASH);
#endif
#ifdef VMS
strcpy((DEFCHAR *)dir_pathname,"");
#endif
strcpy((DEFCHAR *)rexx_pathname,(DEFCHAR *)dir_pathname);
strcpy((DEFCHAR *)key_pathname,(DEFCHAR *)dir_pathname);
strcat((DEFCHAR *)dir_pathname,(DEFCHAR *)dirfilename);
if (splitpath(dir_pathname) != RC_OK)
{
cleanup();
return(18);
}
strcpy((DEFCHAR *)dir_pathname,(DEFCHAR *)sp_path);
strcpy((DEFCHAR *)dir_filename,(DEFCHAR *)sp_fname);
strcat((DEFCHAR *)rexx_pathname,(DEFCHAR *)rexxoutname);
if (splitpath(rexx_pathname) != RC_OK)
{
cleanup();
return(19);
}
strcpy((DEFCHAR *)rexx_pathname,(DEFCHAR *)sp_path);
strcpy((DEFCHAR *)rexx_filename,(DEFCHAR *)sp_fname);
strcat((DEFCHAR *)key_pathname,(DEFCHAR *)keyfilename);
if (splitpath(key_pathname) != RC_OK)
{
cleanup();
return(20);
}
strcpy((DEFCHAR *)key_pathname,(DEFCHAR *)sp_path);
strcpy((DEFCHAR *)key_filename,(DEFCHAR *)sp_fname);
#endif
/*---------------------------------------------------------------------*/
/* Set up a temporary file name for output from PUT command to go... */
/*---------------------------------------------------------------------*/
#if defined(HAVE_BROKEN_TMPNAM)
/*---------------------------------------------------------------------*/
/* Some compliers tmpnam() creates a temporary file name in the current*/
/* directory only, which is not necessarily writeable. We have to work */
/* around this :-( */
/*---------------------------------------------------------------------*/
if ((envptr = getenv("TMP")) == NULL)
{
if ((envptr = getenv("TEMP")) == NULL)
{
if ((envptr = getenv("TMPDIR")) == NULL)
envptr = "C:";
}
}
if ((tmpptr = tmpnam(NULL)) == NULL)
{
cleanup();
return(31);
}
if ((tempfilename = (CHARTYPE *)(*the_malloc)(L_tmpnam+strlen(envptr)+2)) == NULL)
{
cleanup();
return(30);
}
strcpy((DEFCHAR *)tempfilename,envptr);
(void *)strrmdup(strtrans(tempfilename,OSLASH,ISLASH),ISLASH);
if ((tempfilename[strlen((DEFCHAR *)tempfilename)-1]) != ISLASH)
strcat((DEFCHAR *)tempfilename,(DEFCHAR *)ISTR_SLASH);
strcat((DEFCHAR *)tempfilename,tmpptr);
#else
if ((tempfilename = (CHARTYPE *)(*the_malloc)(L_tmpnam)) == NULL)
{
cleanup();
return(30);
}
if ((tempfilename = (CHARTYPE *)tmpnam((DEFCHAR *)tempfilename)) == NULL)
{
cleanup();
return(31);
}
#endif
/*---------------------------------------------------------------------*/
/* Trap signals to exit gracefully, unless user has specified they not */
/* be trapped. */
/*---------------------------------------------------------------------*/
if (trap_signals)
init_signals();
/*---------------------------------------------------------------------*/
/* Set SCREEN values up... */
/*---------------------------------------------------------------------*/
for (i=0;i<VIEW_WINDOWS;i++)
CURRENT_SCREEN.win[i] = (WINDOW *)NULL;
/*---------------------------------------------------------------------*/
/* Set up global defaults. */
/*---------------------------------------------------------------------*/
set_global_defaults();
/*---------------------------------------------------------------------*/
/* Initialise command array to empty strings. */
/*---------------------------------------------------------------------*/
init_command();
/*---------------------------------------------------------------------*/
/* Initialise rexx support. If no REXX available, set flag... */
/*---------------------------------------------------------------------*/
#ifndef MSWIN
rexx_support = TRUE;
if (initialise_rexx() != RC_OK)
rexx_support = FALSE;
#endif
/*---------------------------------------------------------------------*/
/* Set up default screens using the default values of terminal_lines */
/* and terminal_cols. These will be altered after initscr(). */
/*---------------------------------------------------------------------*/
screen[0].sl = screen[1].sl = NULL;
if (batch_only)
{
set_screen_defaults();
/*---------------------------------------------------------------------*/
/* Read each file into memory and apply the profile file to each of the*/
/* files. */
/*---------------------------------------------------------------------*/
current_file_name = first_file_name;
while(current_file_name != NULL)
{
if ((rc = get_file((CHARTYPE *)current_file_name->line)) != RC_OK)
{
cleanup();
if (rc == RC_DISK_FULL)
display_error(57,(CHARTYPE *)"...probably",FALSE);
return(21);
}
pre_process_line(CURRENT_VIEW,0L,(LINE *)NULL);
if (execute_profile)
{
if (local_prf != (CHARTYPE *)NULL)
rc = get_profile(local_prf,prf_arg);
if (error_on_screen)
{
pause_for_errors = TRUE;
error_on_screen = FALSE;
}
#ifdef MSWIN
(void)get_user_profile();
if (error_on_screen)
{
pause_for_errors = TRUE;
error_on_screen = FALSE;
}
#endif
}
current_file_name = current_file_name->next;
}
first_file_name = lll_free(first_file_name);
/*---------------------------------------------------------------------*/
/* If THE has been used only in batch, exit here. */
/*---------------------------------------------------------------------*/
if (number_of_files != 0)
{
sprintf((DEFCHAR *)rec,"%d",number_of_files);
display_error(77,rec,FALSE);
}
cleanup();
return(0);
} /* if (batch_only) */
/*---------------------------------------------------------------------*/
/* If the platform supports the mouse, set up the default commands. */
/*---------------------------------------------------------------------*/
#if defined(MOUSE_SUPPORT_ENABLED)
initialise_mouse_commands();
#endif
/*---------------------------------------------------------------------*/
/* Start up curses. This is done ONLY for interactive sessions! */
/*---------------------------------------------------------------------*/
/* traceon();*/
#if defined(HAVE_SLK_INIT)
# if MAX_SLK == 10
if (SLKx) slk_init(55);
# else
if (SLKx) slk_init(1);
# endif
#endif
#if defined(HAVE_SB_INIT)
if (SBx) sb_init();
#endif
initscr();
curses_started = TRUE;
/*---------------------------------------------------------------------*/
/* Save the value of LINES and COLS and use these for all screen */
/* sizing calculations. This is because BSD scrolls if a character is */
/* displayed in the bottom right corner of the screen :-( */
/*---------------------------------------------------------------------*/
terminal_lines=LINES;
terminal_cols=COLS;
#ifdef HAVE_BSD_CURSES
terminal_lines--;
#endif
/*---------------------------------------------------------------------*/
/* Determine if colour support available. */
/*---------------------------------------------------------------------*/
if (colour_support) /* if default setting not overridden on command line */
{
colour_support = FALSE;
#ifdef A_COLOR
if (has_colors())
{
start_color();
colour_support = TRUE;
init_colour_pairs();
}
#endif
}
/*---------------------------------------------------------------------*/
/* Set various terminal characteristics... */
/*---------------------------------------------------------------------*/
cbreak();
raw();
#if defined(USE_EXTCURSES)
extended(FALSE);
#endif
#if defined(PDCURSES)
raw_output(TRUE);
#endif
nonl();
noecho();
keypad(stdscr,TRUE);
notimeout(stdscr,TRUE);
(void)THETypeahead((CHARTYPE *)"OFF");
/*---------------------------------------------------------------------*/
/* Set up mouse support if enabled in curses library. */
/*---------------------------------------------------------------------*/
#if defined(MOUSE_SUPPORT_ENABLED)
mouse_set(ALL_MOUSE_EVENTS);
#endif
/*---------------------------------------------------------------------*/
/* Set up variables and values dependent on LINES and COLS now with */
/* values set by initscr(). */
/*---------------------------------------------------------------------*/
set_screen_defaults();
#if 0
/*---------------------------------------------------------------------*/
/* For each file being edited, set up the curses windows for each of */
/* them. */
/*---------------------------------------------------------------------*/
if (set_up_windows(0) != RC_OK)
{
cleanup();
return(22);
}
#endif
#if 0
CURRENT_VIEW = CURRENT_SCREEN.screen_view = vd_first;
#endif
#if defined(HAVE_BROKEN_SYSVR4_CURSES)
force_curses_background();
refresh();
#endif
/*---------------------------------------------------------------------*/
/* wnoutrefresh() is called here so that the first call to getch() on */
/* stdscr does not clear the screen. */
/*---------------------------------------------------------------------*/
wnoutrefresh(stdscr);
#if defined(HAVE_SLK_INIT)
if (SLKx) slk_noutrefresh();
#endif
/*---------------------------------------------------------------------*/
/* Create the statusline window... */
/*---------------------------------------------------------------------*/
if (create_statusline_window() != RC_OK)
{
cleanup();
display_error(0,(CHARTYPE *)"creating status line window",FALSE);
return(23);
}
/*---------------------------------------------------------------------*/
/* Set up ETMODE tables... */
/*---------------------------------------------------------------------*/
#if defined(DOS) || defined(OS2) || defined(WIN32)
(void)Etmode((CHARTYPE *)"ON");
#elif defined(XCURSES)
(void)Etmode((CHARTYPE *)"ON 32-255");
#elif defined(UNIX)
(void)Etmode((CHARTYPE *)"OFF");
#endif
/*---------------------------------------------------------------------*/
/* Read each file into memory and apply the profile file to each of the*/
/* files. */
/*---------------------------------------------------------------------*/
current_file_name = first_file_name;
while(current_file_name != NULL)
{
rc = Xedit((CHARTYPE *)current_file_name->line);
if (rc != RC_OK)
{
cleanup();
return(24);
}
current_file_name = current_file_name->next;
}
first_file_name = lll_free(first_file_name);
/*---------------------------------------------------------------------*/
/* If THE has only been used to process a profile file, then exit. */
/*---------------------------------------------------------------------*/
if (number_of_files == 0)
{
cleanup();
return(0);
}
/*---------------------------------------------------------------------*/
/* We are no longer in the profile status. */
/*---------------------------------------------------------------------*/
in_profile = FALSE;
been_interactive = TRUE;
/*---------------------------------------------------------------------*/
/* This is where it all happens. */
/*---------------------------------------------------------------------*/
editor();
/*---------------------------------------------------------------------*/
/* Finalise rexx support... */
/*---------------------------------------------------------------------*/
#ifndef MSWIN
finalise_rexx();
#endif
/*---------------------------------------------------------------------*/
/* Free up the dynamically allocated memory. */
/*---------------------------------------------------------------------*/
if (first_define != NULL)
first_define = dll_free(first_define);
if (first_prefix_synonym != NULL)
first_prefix_synonym = lll_free(first_prefix_synonym);
if (first_mouse_define != NULL)
first_define = dll_free(first_mouse_define);
(*the_free)(rec);
(*the_free)(trec);
(*the_free)(cmd_rec);
(*the_free)(pre_rec);
if (profile_command_line != NULL)
(*the_free)(profile_command_line);
if (screen[0].sl != NULL)
(*the_free)(screen[0].sl);
if (screen[1].sl != NULL)
(*the_free)(screen[1].sl);
/*---------------------------------------------------------------------*/
/* Free memory for temp_params and tmp_cmd */
/*---------------------------------------------------------------------*/
free_temp_space(TEMP_PARAM);
free_temp_space(TEMP_MACRO);
free_temp_space(TEMP_TEMP_CMD);
free_temp_space(TEMP_TMP_CMD);
if (local_prf != NULL)
(*the_free)(local_prf);
if (prf_arg != NULL)
(*the_free)(prf_arg);
free_recovery_list();
if (target_buffer != NULL)
(*the_free)(target_buffer);
#if defined(UNIX) || defined(OS2) || defined(EMX)
(*the_free)(spooler_name);
#endif
if (divider != (WINDOW *)NULL)
{
delwin(divider);
divider = (WINDOW *)NULL;
}
if (error_window != (WINDOW *)NULL)
{
delwin(error_window);
error_window = (WINDOW *)NULL;
}
if (last_message != NULL)
(*the_free)(last_message);
/*---------------------------------------------------------------------*/
/* If the user wants a clearscreen done before exiting, do it... */
/*---------------------------------------------------------------------*/
if (CLEARSCREENx)
{
wclear(stdscr);
move(0,0);
attrset(A_NORMAL);
refresh();
}
else
/*---------------------------------------------------------------------*/
/* ...otherwise, get the cursor to the bottom line. */
/*---------------------------------------------------------------------*/
{
if (statarea != (WINDOW *)NULL)
{
mvwaddstr(statarea,0,4," ");
wattrset(statarea,A_NORMAL);
mvwaddstr(statarea,0,0,"THE - END");
wrefresh(statarea);
}
}
if (statarea != (WINDOW *)NULL)
{
delwin(statarea);
statarea = (WINDOW *)NULL;
}
#ifdef MSWIN
Win31Cleanup();
return(0);
#endif
cleanup();
return(0);
}
/***********************************************************************/
#ifdef HAVE_PROTO
static void init_signals(void)
#else
static void init_signals()
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: init_signals");
#endif
#ifdef UNIX
signal(SIGQUIT,handle_signal);
signal(SIGHUP,handle_signal);
signal(SIGABRT,handle_signal);
signal(SIGFPE,handle_signal);
signal(SIGSEGV,handle_signal);
signal(SIGINT,handle_signal);
signal(SIGTERM,handle_signal);
# if defined(SIGBUS)
signal(SIGBUS,handle_signal);
# endif
#endif
#ifdef TRACE
trace_return();
#endif
return;
}
/***********************************************************************/
#ifdef HAVE_PROTO
void init_colour_pairs(void)
#else
void init_colour_pairs()
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
register int fg=0,bg=0;
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: init_colour_pairs");
#endif
#ifdef A_COLOR
for (fg=0;fg<COLORS;fg++)
{
for (bg=0;bg<COLORS;bg++)
{
if (ATTR2PAIR(fg,bg) <= COLOR_PAIRS)
init_pair(ATTR2PAIR(fg,bg),fg,bg);
}
}
#endif
#ifdef TRACE
trace_return();
#endif
return;
}
/***********************************************************************/
#ifdef HAVE_PROTO
int setup_profile_files(CHARTYPE *specified_prf)
#else
int setup_profile_files(specified_prf)
CHARTYPE *specified_prf;
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
int rc=RC_OK;
char *envptr=NULL;
/*--------------------------- processing ------------------------------*/
/*---------------------------------------------------------------------*/
/* If a profile specified on the command line, set it up as the local */
/* profile. It MUST exist and be readable, otherwise an error. */
/*---------------------------------------------------------------------*/
if (specified_prf != (CHARTYPE *)NULL)
{
if ((local_prf = (CHARTYPE *)(*the_malloc)((MAX_FILE_NAME+1)*sizeof(CHARTYPE))) == NULL)
return(RC_OUT_OF_MEMORY);
strcpy((DEFCHAR *)local_prf,(DEFCHAR *)specified_prf);
if (!file_exists(local_prf))
{
display_error(9,local_prf,FALSE);
return(RC_FILE_NOT_FOUND);
}
/*---------------------------------------------------------------------*/
/* If the file is not readable, error. */
/*---------------------------------------------------------------------*/
if (!file_readable(local_prf))
{
display_error(8,local_prf,FALSE);
return(RC_ACCESS_DENIED);
}
return(rc);
}
/*---------------------------------------------------------------------*/
/* If a profile specified with THE_PROFILE_FILE, set it up as the local*/
/* profile. It does not have to exist. */
/*---------------------------------------------------------------------*/
if ((envptr = getenv("THE_PROFILE_FILE")) != NULL)
{
if ((local_prf = (CHARTYPE *)(*the_malloc)((MAX_FILE_NAME+1)*sizeof(CHARTYPE))) == NULL)
return(RC_OUT_OF_MEMORY);
strcpy((DEFCHAR *)local_prf,envptr);
return(rc);
}
/*---------------------------------------------------------------------*/
/* No specific profile, so check for default profiles. */
/*---------------------------------------------------------------------*/
if ((local_prf = (CHARTYPE *)(*the_malloc)((MAX_FILE_NAME+1)*sizeof(CHARTYPE))) == NULL)
return(RC_OUT_OF_MEMORY);
/*---------------------------------------------------------------------*/
/* For Unix, use a local profile first... */
/*---------------------------------------------------------------------*/
#if defined(UNIX)
strcpy((DEFCHAR *)local_prf,(DEFCHAR *)user_home_dir);
strcat((DEFCHAR *)local_prf,(DEFCHAR *)THE_PROFILE_FILE);
(void *)strrmdup(strtrans(local_prf,OSLASH,ISLASH),ISLASH);
if (file_readable(local_prf))
return(rc);
#endif
/*---------------------------------------------------------------------*/
/* If no local profile, see if a global profile exists... */
/*---------------------------------------------------------------------*/
strcpy((DEFCHAR *)local_prf,(DEFCHAR *)the_home_dir);
strcat((DEFCHAR *)local_prf,(DEFCHAR *)THE_PROFILE_FILE);
(void *)strrmdup(strtrans(local_prf,OSLASH,ISLASH),ISLASH);
if (file_readable(local_prf))
return(rc);
/*---------------------------------------------------------------------*/
/* To get here, no profile files to be executed. */
/*---------------------------------------------------------------------*/
(*the_free)(local_prf);
local_prf = (CHARTYPE *)NULL;
return(rc);
}
/***********************************************************************/
#ifdef HAVE_PROTO
static void display_info(CHARTYPE *argv0)
#else
static void display_info(argv0)
CHARTYPE *argv0;
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
fprintf(stderr,"\nTHE %s %2s %s. All rights reserved.\n",the_version,the_release,the_copyright);
fprintf(stderr,"THE is distributed under the terms of the GNU General Public License \n");
fprintf(stderr,"and comes with NO WARRANTY. See the file COPYING for details.\n");
fprintf(stderr,"\nUsage:\n\n%s [-h?nmrsbk] [-p profile] [-a profile_arg] [-w width] [-u display_length] [[dir] [file [...]]]\n",argv0);
fprintf(stderr,"\nwhere:\n\n");
fprintf(stderr,"-h,-? show this message\n");
fprintf(stderr,"-n do not execute a profile file\n");
fprintf(stderr,"-m force display into mono\n");
fprintf(stderr,"-r run THE in read-only mode\n");
fprintf(stderr,"-s turn off signal trapping (Unix only)\n");
fprintf(stderr,"-b run in batch mode\n");
fprintf(stderr,"-k allow Soft Label Key display\n");
fprintf(stderr,"-p profile filename of profile file\n");
fprintf(stderr,"-a profile_arg argument(s) to profile file (only with REXX)\n");
fprintf(stderr,"-w width maximum width of line (default 512)\n");
fprintf(stderr,"-u display_length display length in non-line mode\n");
fprintf(stderr,"[dir [file [...]]] file(s) and/or directory to be edited\n\n");
fflush(stderr);
return;
}
/***********************************************************************/
#ifdef HAVE_PROTO
int allocate_working_memory(void)
#else
int allocate_working_memory()
#endif
/***********************************************************************/
{
/*-------------------------- external data ----------------------------*/
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: allocate_working_memory");
#endif
/*---------------------------------------------------------------------*/
/* Allocate some memory to rec. */
/*---------------------------------------------------------------------*/
if (rec == NULL)
rec = (CHARTYPE *)(*the_malloc)((max_line_length+5)*sizeof(CHARTYPE));
else
rec = (CHARTYPE *)(*the_realloc)(rec,(max_line_length+5)*sizeof(CHARTYPE));
if (rec == NULL)
return(10);
/*---------------------------------------------------------------------*/
/* Allocate some memory to trec; buffer for reading files. */
/*---------------------------------------------------------------------*/
trec_len = max((LENGTHTYPE)(30*80),(LENGTHTYPE)((max_line_length+2)*2));
if (trec == NULL)
trec = (CHARTYPE *)(*the_malloc)(trec_len*sizeof(CHARTYPE));
else
trec = (CHARTYPE *)(*the_realloc)(trec,trec_len*sizeof(CHARTYPE));
if (trec == NULL)
return(11);
/*---------------------------------------------------------------------*/
/* Allocate memory to cmd_rec and set it to blanks. */
/*---------------------------------------------------------------------*/
if (cmd_rec == NULL)
cmd_rec = (CHARTYPE *)(*the_malloc)((max_line_length+2)*sizeof(CHARTYPE));
else
cmd_rec = (CHARTYPE *)(*the_realloc)(cmd_rec,(max_line_length+2)*sizeof(CHARTYPE));
if (cmd_rec == NULL)
return(12);
memset(cmd_rec,' ',max_line_length);
cmd_rec_len = 0;
/*---------------------------------------------------------------------*/
/* Allocate some memory for temporary space... */
/*---------------------------------------------------------------------*/
if (allocate_temp_space(max_line_length,TEMP_PARAM) != RC_OK)
return(13);
if (allocate_temp_space(max_line_length,TEMP_TMP_CMD) != RC_OK)
return(14);
if (allocate_temp_space(max_line_length,TEMP_TEMP_CMD) != RC_OK)
return(15);
/*---------------------------------------------------------------------*/
/* Allocate some memory to profile_command_line. (only really need to */
/* do this if NO REXX support). */
/*---------------------------------------------------------------------*/
if (profile_command_line == NULL)
profile_command_line = (CHARTYPE *)(*the_malloc)((max_line_length+2)*sizeof(CHARTYPE));
else
profile_command_line = (CHARTYPE *)(*the_realloc)(profile_command_line,(max_line_length+2)*sizeof(CHARTYPE));
if (profile_command_line == NULL)
return(17);
return(0);
}
/***********************************************************************/
#ifdef HAVE_PROTO
void cleanup(void)
#else
void cleanup()
#endif
/***********************************************************************/
{
/*-------------------------- external data ----------------------------*/
#ifndef XCURSES
extern bool CLEARSCREENx;
#endif
extern bool INSERTMODEx;
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: cleanup");
#endif
if (curses_started)
{
#ifdef XCURSES
if (error_on_screen)
{
display_error(0,(CHARTYPE *)HIT_ANY_KEY,FALSE);
wrefresh(error_window);
(void)getch();
}
#else
if (error_on_screen)
wrefresh(error_window);
#endif
INSERTMODEx=FALSE;
draw_cursor(TRUE);
#ifdef HAVE_BSD_CURSES
nl();
echo();
#endif
endwin();
#ifdef XCURSES
XCursesExit();
#endif
curses_started = FALSE;
}
#ifndef XCURSES
if (!CLEARSCREENx
&& been_interactive)
printf("\n");
#endif
if (tempfilename)
{
if (file_exists(tempfilename))
remove_file(tempfilename);
(*the_free)(tempfilename);
}
/*
* Free up the working memory
*/
the_free_flists();
#ifdef TRACE
trace_return();
#endif
return;
}
#ifdef UNIX
/***********************************************************************/
#ifdef HAVE_PROTO
static RETSIGTYPE handle_signal(int err)
#else
static RETSIGTYPE handle_signal(err)
int err;
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
FILE_DETAILS *cf;
VIEW_DETAILS *curr;
bool process_view=FALSE;
FILE_DETAILS *first_view_file=NULL;
register int j=0;
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: handle_signal");
#endif
/*
* For each file in the ring, execute an AUTOSAVE on it and then
* die.
*/
if (curses_started)
{
endwin();
#ifdef XCURSES
XCursesExit();
#endif
curses_started = FALSE;
}
fprintf(stderr,"\nTHE terminated with signal: %d\n\n",err);
curr = vd_current;
for (j=0;j<number_of_files;)
{
process_view = TRUE;
if (curr->file_for_view->file_views > 1)
{
if (first_view_file == curr->file_for_view)
process_view = FALSE;
else
first_view_file = curr->file_for_view;
}
if (process_view)
{
j++;
cf = curr->file_for_view;
if (!cf->pseudo_file)
{
fprintf(stderr,"Attempting to autosave: %s%s\n",cf->fpath,cf->fname);
save_file(cf,cf->autosave_fname,TRUE,cf->number_lines,1L,NULL,FALSE,0,max_line_length,TRUE,FALSE);
}
}
curr = curr->next;
if (curr == NULL)
curr = vd_first;
}
/*
* Lets not push our luck in the signal handler, and just die...
*/
exit(25);
}
#endif