This is ledit.c in view mode; [Download] [Up]
/*
* Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu)
* All Rights Reserved.
*/
#include <config.h>
#include <stdio.h>
#include <slang.h>
#include <string.h>
#ifdef pc_system
# include <fcntl.h>
#endif
#ifdef MSWINDOWS
# ifndef __WIN32__
# include <toolhelp.h>
# else
# include <windows.h>
# endif
#endif
#include "buffer.h"
#include "keymap.h"
#include "file.h"
#include "ins.h"
#include "ledit.h"
#include "screen.h"
#include "window.h"
#include "display.h"
#include "search.h"
#include "misc.h"
#include "replace.h"
#include "paste.h"
#include "sysdep.h"
#include "cmds.h"
#include "text.h"
#include "hooks.h"
#include "undo.h"
#define JED_PROMPT "S-Lang>"
#ifdef HAS_SUBPROCESSES
#include "jprocess.h"
#endif
Buffer *MiniBuffer;
Buffer *Last_Buffer;
char *Token_Pointer;
Buffer *The_MiniBuffer; /* this never gets deleted since we may need it */
Window_Type *The_MiniWindow;
extern char *get_cwd(void);
int Ignore_Beep = 0;
int MiniBuffer_Active = 0;
User_Variable_Type User_Vars =
{
78, /* wrap-column */
8, /* tabs */
3, /* c_indent */
2, /* c_brace */
300, /* max_hits */
};
#ifdef pc_system
char Jed_Library[256];
#else
char Jed_Library[1024];
#endif
int (*complete_open)(char *);
int (*complete_next)(char *);
static int Buf_List_Len;
Buffer *Buf_Context;
static char *Expect_File_Error = "Expecting filename.";
static char *Keymap_Error = "Unknown_Keymap";
/* read doc file */
int get_doc_string(char *f, char *file)
{
char *buf, *b, *f1;
VFILE *fp;
int ret = 0;
unsigned int n;
char nline = 1; /* ascii value of line term (^A) */
if (*f == 0) return(0);
if ((fp = vopen(file, 1024, VFILE_TEXT)) == NULL) return(0);
while ((buf = vgets(fp, &n)) != NULL)
{
f1 = f; b = buf;
while (*f1 && (*f1 == *b)) f1++, b++;
if (*f1) continue;
b = buf;
b[n - 1] = 0;
while (*b)
{
if (*b == nline) *b = '\n';
b++;
}
SLang_push_string(buf + 1); /* lose the prefix */
ret = 1;
break;
}
vclose(fp);
return(ret);
}
static int next_bufflist(char *buf)
{
Buffer *tthis;
while (1)
{
tthis = Buf_Context;
if (tthis == MiniBuffer) return(0);
Buf_Context = Buf_Context->next;
#ifdef __os2__
if (!Buf_List_Len || !strncmpi(buf, tthis->name, Buf_List_Len))
#else
if (!Buf_List_Len || !strncmp(buf, tthis->name, Buf_List_Len))
#endif
{
if (*tthis->name == ' ') continue; /* internal buffers */
strcpy(buf, tthis->name);
return(1);
}
}
}
static int open_bufflist(char *buf)
{
if ((Buf_Context = MiniBuffer) == NULL) return(0);
Buf_Context = Buf_Context->next;
Buf_List_Len = strlen(buf);
return next_bufflist(buf);
}
char *what_buffer()
{
return (CBuf->name);
}
int bufferp(char *name)
{
if (NULL == find_buffer(name)) return(0); else return(1);
}
int insert_buffer_name(char *name)
{
Buffer *buf;
if (NULL != (buf = find_buffer(name)))
{
insert_buffer(buf);
return(1);
}
else msg_error("Unable to find buffer.");
return(0);
}
int replace_cmd(char *old, char *neew)
{
int n = 0;
CHECK_READ_ONLY
push_spot ();
if (search(old, 1, 0)) while(replace_next(old, neew)) n++;
pop_spot();
return n;
}
static Buffer *find_scratch_buffer (void)
{
char *sname = "*scratch*";
Buffer *scratch;
scratch = find_buffer (sname);
if (NULL == scratch)
{
scratch = make_buffer();
strcpy(scratch->name, sname);
strcpy(scratch->dir, CBuf->dir);
*scratch->file = 0;
}
return scratch;
}
/* Try to find any other buffer but kill_buf such that the buffer is not
* visible, not scratch and not buried.
*/
static Buffer *find_non_visible_buffer (Buffer *kill_buf)
{
Buffer *buf, *scratch;
buf = kill_buf->next;
scratch = find_scratch_buffer ();
while ((buf != kill_buf) &&
((*buf->name == ' ') || (buf->flags & BURIED_BUFFER)
|| (buf == scratch) || (buffer_visible(buf))))
{
buf = buf->next;
}
if (buf == kill_buf) buf = scratch;
return buf;
}
int kill_buffer_cmd(char *name)
{
Buffer *this_buf, *kill_buf, *scratch, *buf;
Window_Type *w;
int kill;
if (NULL == (kill_buf = find_buffer(name)))
{
msg_error("Buffer does not exist.");
return(0);
}
this_buf = CBuf;
switch_to_buffer(kill_buf);
#ifdef HAS_SUBPROCESSES
if (kill_buf->locked)
{
erase_buffer ();
switch_to_buffer (this_buf);
return 0;
}
#endif
kill = 1;
if ((*name != ' ') && (kill_buf->flags & BUFFER_TRASHED))
{
char msgbuf[256];
sprintf (msgbuf,"Buffer %s modified. Kill, Save First, Abort: [KSA]", name);
flush_message(msgbuf);
/* This does not go through keyboard macro routines
on purpose! */
switch (my_getkey())
{
case 'k': case 'K': kill = 1; break;
case 's': case 'S': kill = 2; break;
default: msg_error("Aborted."); return(0);
}
clear_message ();
}
if (kill == 2)
{
write_buffer();
if (SLang_Error)
{
switch_to_buffer(this_buf);
return(0);
}
}
/* if it is the scratch buffer, just erase it since we are going to
recreate it anyway. */
scratch = find_scratch_buffer ();
if (kill_buf == scratch)
{
erase_buffer();
#ifdef HAS_SUBPROCESSES
if (kill_buf->subprocess) jed_kill_process (kill_buf->subprocess - 1);
#endif
switch_to_buffer(this_buf);
return 1;
}
/* find a buffer to replace this one with if it is in a window */
if (buffer_visible(kill_buf))
{
buf = find_non_visible_buffer (kill_buf);
/* search through windows looking for the buffer and replace it */
w = JWindow;
do
{
if (kill_buf == JWindow->buffer)
{
touch_window_hard (JWindow, 0);
window_buffer(buf); /* I should choose a different one
every time */
}
JWindow = JWindow->next;
}
while (w != JWindow);
}
else buf = scratch;
if (kill_buf == Last_Buffer) Last_Buffer = NULL;
if (kill_buf == this_buf) this_buf = buf;
switch_to_buffer(this_buf);
delete_buffer(kill_buf);
return(1);
}
int write_buffer_cmd(char *filestr)
{
#ifdef VMS
char *ff;
#endif
char dir[256], *f, file[256];
char msgstr[132];
int n;
#ifdef REAL_UNIX_SYSTEM
f = expand_link(filestr);
#else
f = expand_filename(filestr);
#endif
strncpy(file, f, 255); file[255] = 0;
f = extract_file(file);
if ((*f == 0) && (*CBuf->file == 0))
{
msg_error("Filename Required.");
return(0);
}
n = (int) (f - file);
MEMCPY((char *) dir, (char *) file, n);
dir[n] = 0;
if (*f == 0) f = CBuf->file;
n = write_file_with_backup(dir, f);
if (n >= 0)
{
#ifdef VMS
ff = f; while (*ff) if (*ff == ';') *ff = 0; else ff++;
#endif
if (Batch != 2)
{
sprintf(msgstr,"Wrote %d lines to %s%s", n, dir, f);
message(msgstr);
}
CBuf->flags &= ~BUFFER_TRASHED;
CBuf->flags |= AUTO_SAVE_BUFFER;
CBuf->hits = 0;
#ifdef UNDO_HAS_REDO
update_undo_unchanged ();
#endif
visit_file(dir, f);
return(1);
}
else
{
sprintf(msgstr,"Error writing file %s%s", dir, f);
msg_error(msgstr);
return(0);
}
}
#if defined(msdos) && !defined(__WATCOMC__) && !defined(MSWINDOWS)
int show_memory()
{
struct farheapinfo hi;
char buf[132];
char *c;
unsigned long total = 0, core, used = 0;
unsigned long max = 0;
int i = 0;
hi.ptr = NULL;
if (farheapcheck() == _HEAPCORRUPT) c = "corrupt"; else c = "ok";
while (farheapwalk(&hi) == _HEAPOK)
{
if (hi.in_use)
used += hi.size;
else
{
total += hi.size;
if (hi.size > max) max = hi.size;
i++;
}
}
core = farcoreleft();
sprintf(buf, "used:%lu, core:%lu, free:%lu, grand:%lu, max:%lu, frag:%d (%s)",
used, core, total, core + total, max, i, c);
message(buf);
return (0);
}
#endif
#ifdef MSWINDOWS
int show_memory (void)
{
char buf[132];
#ifndef __WIN32__
MEMMANINFO mmi;
if (MemManInfo(&mmi))
{
sprintf(buf, "tot pages: %lu, free pages: %lu",
mmi.dwTotalLinearSpace, mmi.dwFreeLinearSpace);
message(buf);
}
#else
MEMORYSTATUS mst;
GlobalMemoryStatus(&mst);
sprintf(buf, "avail space: %lu, tot phys space: %lu, avail phys space: %lu",
mst.dwAvailPhys + mst.dwAvailPageFile, mst.dwTotalPhys, mst.dwAvailPhys);
message(buf);
#endif
return 0;
}
#endif
#ifdef __WATCOMC__
#include <malloc.h>
int show_memory()
{
char buf[132];
sprintf(buf, "avail mem: %lu, tot phys pgs: ???, free lin space: %lu",
_memavl (), _memmax ());
message(buf);
return (0);
}
#endif
#ifdef __GO32__
#include <dpmi.h>
int show_memory()
{
char buf[132];
unsigned long mem;
_go32_dpmi_meminfo info;
_go32_dpmi_get_free_memory_information(&info);
if (info.available_physical_pages != -1)
mem = info.available_physical_pages * 4096;
else mem = info.available_memory;
sprintf(buf, "avail mem: %lu, tot phys pgs: %lu, free lin space: %lu",
mem, info.total_physical_pages, info.free_linear_space);
message(buf);
return (0);
}
#endif
int set_buffer(char *name)
{
Buffer *buf;
if ((name == NULL) || (*name == 0))
{
msg_error("set_buffer: Buffer name is NULL");
return (0);
}
/* Last_Buffer = CBuf; */
if (NULL == (buf = find_buffer(name)))
{
buf = make_buffer();
strcpy(buf->dir, CBuf->dir);
*buf->file = 0;
switch_to_buffer(buf);
uniquely_name_buffer(name);
}
else switch_to_buffer(buf);
return(1);
}
int get_yes_no(char *question)
{
char buf[256], *tmp;
int n;
strncpy(buf, question, 240); buf[240] = 0;
strcat(buf, "? (yes or no)");
while(1)
{
if (NULL == (tmp = read_from_minibuffer(buf, 0, NULL, &n))) return(-1);
if (!strcmp(tmp, "yes"))
{
SLFREE(tmp);
return(1);
}
if (!strcmp(tmp, "no"))
{
SLFREE(tmp);
return(0);
}
msg_error("yes or no!");
SLFREE(tmp);
}
}
int find_file_cmd(char *filestr) /* filestr is const ! */
{
char *f, *file, filebuf[256];
char msgstr[132];
Buffer *buf;
int n;
#ifdef REAL_UNIX_SYSTEM
file = expand_link(filestr);
#else
file = expand_filename(filestr);
#endif
safe_strcpy(filebuf, file, sizeof (filebuf));
file = filebuf;
f = extract_file(file);
if ((*file == 0) || (*f == 0))
{
msg_error(Expect_File_Error);
return(0);
}
check_buffers ();
/* search for the file in current buffer list */
if (NULL != (buf = find_file_buffer(file)))
{
if (file_changed_on_disk(file))
{
if (get_yes_no("File changed on disk. Read From Disk"))
{
if (*Error_Buffer) return(1);
n = (int) buf->linenum;
buf->flags &= ~BUFFER_TRASHED;
kill_buffer_cmd(buf->name);
find_file_cmd(file);
goto_line(&n);
return(1);
}
}
switch_to_buffer (buf);
return(1);
}
buf = make_buffer();
switch_to_buffer(buf);
buffer_filename(file, NULL);
n = read_file(file);
CLine = CBuf->beg;
Point = 0;
LineNum = 1;
if (CLine == NULL) make_line(25);
set_file_modes();
CBuf->flags |= UNDO_ENABLED;
switch(n)
{
case -2: msg_error("File not readable."); break;
default:
if (Batch == 2) break;
if (*Message_Buffer) break; /* autosave warning? */
if (n == -1) message("New file.");
else
{
sprintf(msgstr,"%d lines read", n);
message(msgstr);
}
}
SLang_run_hooks("find_file_hook", file, NULL);
return(1);
}
int find_file_in_window(char *file)
{
int ret;
Buffer *b = CBuf;
ret = find_file_cmd(file);
if ((b != CBuf) && (*CBuf->name != ' ')) Last_Buffer = CBuf;
window_buffer(CBuf);
return(ret);
}
void set_mode_cmd(char *mode, int *flags)
{
char *m = CBuf->mode_str;
CBuf->modes = *flags;
strncpy((char *) m, (char *) mode, 12);
m[12] = 0;
}
/* create a minibuffer with window and switch to it. */
static void create_minibuffer(void)
{
Window_Type *w;
MiniBuffer = The_MiniBuffer;
/* I want to make Mini_Window->next = Current Window so that scroll other
window routines will scroll it. */
w = JWindow;
do other_window(); while (JWindow->next != w);
JWindow->next = The_MiniWindow;
The_MiniWindow->next = w;
The_MiniWindow->column = 1;
Mini_Info.action_window = w;
other_window(); /* now in minibuffer window */
window_buffer(MiniBuffer);
switch_to_buffer(MiniBuffer);
MiniBuffer_Active = 1;
erase_buffer ();
/* allow kill region to kill to beginning of minibuffer.
* Suggested by stefen@uni-paderborn.de */
push_mark ();
}
char *Completion_Buffer = "*Completions*";
static char *Last_Completion_Buffer;
static int Last_Completion_Windows;
/* evaluate command in minibuffer and leave */
int exit_minibuffer()
{
if (IS_MINIBUFFER)
{
if (Last_Completion_Buffer != NULL)
{
pop_to_buffer (Completion_Buffer);
CBuf->flags &= ~BUFFER_TRASHED;
switch_to_buffer_cmd (Last_Completion_Buffer);
kill_buffer_cmd (Completion_Buffer);
touch_window_hard (JWindow, 0);
if (Last_Completion_Windows == 1) one_window ();
}
select_minibuffer ();
Exit_From_MiniBuffer = 1;
}
Last_Completion_Buffer = NULL;
return(0);
}
/* return 1 if minibuffer already exists otherwise returns 0 */
int select_minibuffer()
{
Window_Type *w;
/* Try to find active minibuffer and go there */
w = JWindow;
while (MiniBuffer != NULL)
{
if (JWindow->top == *tt_Screen_Rows) return(1);
other_window();
if (w == JWindow) exit_error("Internal Error: no window!", 1);
}
/* switchs to minibuffer too */
create_minibuffer();
return(0);
}
/* if cmd != NULL, insert it into minibuffer and then send the result to
the appropriate routine. */
static int ledit(void)
{
int n;
char *tmp;
if (MiniBuffer == NULL) complete_open = NULL;
if (NULL == (tmp = read_from_minibuffer(JED_PROMPT, 0, NULL, &n))) return(0);
SLang_Error = 0;
Suspend_Screen_Update = 1;
SLang_load_string(tmp);
SLFREE(tmp);
if ((SLang_Error == -1) && SLKeyBoard_Quit)
{
msg_error("Quit!");
}
SLang_Error = 0;
return(1);
}
static char *read_file_from_minibuffer(char *prompt, char *def)
{
int n;
char buf[256];
complete_open = sys_findfirst;
complete_next = sys_findnext;
if (*CBuf->dir == 0) strcpy(CBuf->dir, get_cwd());
strcpy(buf, CBuf->dir);
return read_from_minibuffer(prompt, def, buf, &n);
}
static char *String_Completion_Str;
static char *String_Completion_Str_Next;
static int String_Completion_Str_Len;
static int next_string_list (char *buf)
{
register char *s = String_Completion_Str_Next;
int len;
while (*s)
{
while (*s && (*s != ',')) s++;
len = (int) (s - String_Completion_Str_Next);
if (*s == ',') s++;
if (!len
|| strncmp (buf, String_Completion_Str_Next, String_Completion_Str_Len))
{
String_Completion_Str_Next = s;
continue;
}
if (len > 255) len = 255;
strncpy (buf, String_Completion_Str_Next, len);
buf[len] = 0;
String_Completion_Str_Next = s;
return 1;
}
String_Completion_Str_Next = s;
return 0;
}
static int open_string_list (char *buf)
{
String_Completion_Str_Next = String_Completion_Str;
String_Completion_Str_Len = strlen (buf);
return next_string_list (buf);
}
void read_object_with_completion(char *prompt, char *dflt, char *stuff, int *typep)
{
int type = *typep, n;
char buf[256], *tmp;
char *str = NULL;
int dofree = 0;
*buf = 0;
if (type == 'f') /* file */
{
complete_open = sys_findfirst;
complete_next = sys_findnext;
if (*CBuf->dir == 0) strcpy(CBuf->dir, get_cwd());
strcpy(buf, CBuf->dir);
}
else if (type == 'b') /* buffer */
{
complete_open = open_bufflist;
complete_next = next_bufflist;
}
else if (type == 'F') /* function */
{
complete_open = open_function_list;
complete_next = next_function_list;
}
else if (type == 's')
{
complete_open = open_string_list;
complete_next = next_string_list;
if (SLang_pop_string (&str, &dofree)) return;
String_Completion_Str = str;
}
else
{
complete_open = NULL;
}
strcat (buf, stuff);
if (NULL != (tmp = read_from_minibuffer(prompt, dflt, buf, &n)))
{
if (type == 'f') SLang_push_string(expand_filename(tmp));
else SLang_push_string(tmp);
SLFREE(tmp);
if (dofree) SLFREE (str);
}
}
int insert_file_cmd()
{
char *filebuf, *f, *file;
CHECK_READ_ONLY
if (NULL == (filebuf = read_file_from_minibuffer("Insert file:", NULL))) return(0);
file = expand_filename(filebuf);
SLFREE (filebuf);
f = extract_file(file);
if ((*file == 0) || (*f == 0))
{
msg_error(Expect_File_Error);
return(1);
}
if (insert_file(file) < 0) msg_error("Error inserting file.");
return(1);
}
int find_file()
{
char *tmp;
if (NULL == (tmp = read_file_from_minibuffer("Find file:", (char *) NULL))) return(0);
find_file_in_window(tmp);
SLFREE(tmp);
return(0);
}
int write_buffer()
{
char *tmp;
if (NULL == (tmp = read_file_from_minibuffer("Write to file:", (char *) NULL))) return(0);
write_buffer_cmd(tmp);
SLFREE(tmp);
return(1);
}
void switch_to_buffer_cmd(char *name)
{
Buffer *tthis = CBuf;
set_buffer(name);
window_buffer(CBuf);
if ((CBuf != tthis) && (*CBuf->name != ' ')) Last_Buffer = tthis;
}
static void get_last_buffer(void)
{
if ((Last_Buffer == CBuf) || (Last_Buffer == NULL)
|| (*Last_Buffer->name == ' ')
|| (Last_Buffer->flags & BURIED_BUFFER))
{
Last_Buffer = find_non_visible_buffer (CBuf);
}
}
int get_buffer()
{
char *tmp;
int n;
complete_open = open_bufflist;
complete_next = next_bufflist;
get_last_buffer ();
if (NULL == (tmp = read_from_minibuffer("Switch to buffer:", Last_Buffer->name, NULL, &n))) return(0);
switch_to_buffer_cmd(tmp);
SLFREE(tmp);
return(1);
}
int kill_buffer (void)
{
char *tmp;
int n;
complete_open = open_bufflist;
complete_next = next_bufflist;
tmp = read_from_minibuffer("Kill buffer:", (char *) CBuf->name, NULL, &n);
if (tmp != NULL)
{
#ifdef HAS_SUBPROCESSES
Buffer *b = find_buffer(tmp);
if ((b != NULL) && (b->subprocess))
{
if (0 == get_yes_no("Buffer has a subprocess attached. Delete anyway"))
return 0;
}
#endif
kill_buffer_cmd(tmp);
SLFREE(tmp);
return(1);
}
return 0;
}
int evaluate_cmd()
{
return(!ledit());
}
void insert_string(char *s)
{
CHECK_READ_ONLY_VOID
ins_chars((unsigned char *) s, strlen(s));
}
/* This is weird, Ultrix cc will not compile if set_key comes before unset_key */
void unset_key(char *key)
{
SLang_undefine_key(key, Global_Map);
}
void set_key(char *function, char *key)
{
SLang_define_key(key, function, Global_Map);
}
void unset_key_in_keymap(char *key, char *map)
{
SLKeyMap_List_Type *kmap;
if (NULL == (kmap = SLang_find_keymap(map)))
{
msg_error(Keymap_Error);
return;
}
SLang_undefine_key(key, kmap);
}
int keymap_p(char *name)
{
return ! (NULL == SLang_find_keymap(name));
}
void set_key_in_keymap(char *f, char *key, char *map)
{
SLKeyMap_List_Type *kmap;
if (NULL == (kmap = SLang_find_keymap(map)))
{
msg_error(Keymap_Error);
return;
}
SLang_define_key(key, f, kmap);
}
char *pop_to_buffer(char *name)
{
Window_Type *w, *action, *use_this;
char *bname;
Line *line, *oldline;
int p, oldp, lnum, oldlnum;
Buffer *b, *oldb;
if (!strcmp(name, " <mini>"))
{
select_minibuffer ();
return CBuf->name;
}
/* save position so we can pop back to it if buffer already exists in
window */
oldb = CBuf; oldline = CLine; oldp = Point; oldlnum = LineNum;
set_buffer(name);
line = CLine; p = Point; lnum = LineNum;
use_this = NULL;
if (MiniBuffer != NULL)
{
action = Mini_Info.action_window;
}
else action = NULL;
if (Batch) return CBuf->name;
w = JWindow;
/* find a window to use */
do
{
if (w->top != *tt_Screen_Rows)
{
if (action != NULL)
{
if (w != action) use_this = w;
}
else if (w != JWindow) use_this = w;
if (w->buffer == CBuf)
{
use_this = w;
break;
}
}
w = w->next;
}
while (w != JWindow);
b = CBuf;
if (use_this != NULL)
{
while(JWindow != use_this) other_window();
/* This is a good reason for haveing otherwindow avoid switching buffers */
if (CBuf == oldb)
{
CLine = oldline; Point = oldp; LineNum = oldlnum;
}
}
else
{
if (action != NULL) while(JWindow != action) other_window();
split_window();
/*
* doing it this way makes screen update look better
*/
w = JWindow;
do
{
other_window();
}
while (JWindow->buffer != w->buffer);
JWindow->column = 1;
}
bname = CBuf->name;
switch_to_buffer(b);
b->line = CLine = line;
b->point = Point = p;
b->linenum = LineNum = lnum;
if (b != JWindow->buffer) window_buffer(b);
return bname;
}
/* return number of windows */
int num_windows()
{
Window_Type *w;
int i = 0;
w = JWindow->next;
while (i++, w != JWindow) w = w->next;
return(i);
}
/* I need to make this take another parameter which indicates what to do
* with the cursor rather than sticking it at the end. Call the parameter p.
* Then try:
* if (p <= 0) p = strlen(Message_Buffer) + 1;
* tt_goto_rc(Screen_Height, p); */
void flush_message(char *m)
{
message(m);
if ((JScreen[0].old == NULL) || Batch) return;
do_dialog(Message_Buffer);
tt_goto_rc(*tt_Screen_Rows - 1, strlen(Message_Buffer));
*Message_Buffer = 0;
JWindow->trashed = 1;
flush_output ();
}
#if defined (REAL_UNIX_SYSTEM) || defined (__os2__)
# if defined (__BORLANDC__) || defined (_MSC_VER)
# define popen _popen
# define pclose _pclose
# endif
static char *Process_Error = "Unable to open process.";
int shell_command(char *cmd)
{
FILE *pp;
VFILE *vp;
if (Jed_Secure_Mode)
{
msg_error ("Access denied.");
return -1;
}
if (NULL == (pp = popen(cmd, "r")))
{
msg_error(Process_Error);
return -1;
}
if (NULL != (vp = vstream(fileno(pp), 0, VFILE_BINARY)))
{
(void) insert_file_pointer(vp);
if (vp->buf != NULL) SLFREE(vp->buf);
SLFREE(vp);
}
else msg_error("Malloc Error.");
return pclose(pp);
}
int pipe_region(char *cmd)
{
FILE *pp;
int n;
if (Jed_Secure_Mode)
{
msg_error ("Access denied.");
return -1;
}
if (NULL == (pp = popen(cmd, "w")))
{
msg_error(Process_Error);
return(-1);
}
n = write_region_to_fp(fileno(pp));
if (n == -1)
msg_error ("pipe_region: write failed");
return pclose(pp);
}
#endif
/* called by SLang_load_file
Try to open a .slc then a .sl
*/
#ifdef msdos
#define VFILE_BUF_SIZE 1024
#else
#define VFILE_BUF_SIZE 4096
#endif
static VFILE *jed_open_lib_file(char *file)
{
char *lib = Jed_Library, libfsl[256], libfslc[256], *libp, buff[256],
*type, *libf;
int n, comma = ',';
VFILE *vp;
#ifdef VMS
int vmsn;
#endif
if (*file == '.') lib = "";
else if (*lib == 0)
{
exit_error("JED_ROOT environment variable needs set.", 0);
}
n = 0;
type = file_type(file);
while (1)
{
libp = SLang_extract_list_element(lib, &n, &comma);
n++;
safe_strcpy(libfsl, libp, sizeof (libfsl));
fixup_dir(libfsl);
safe_strcat(libfsl, file, sizeof (libfsl));
strcpy(libfsl, expand_filename(libfsl));
if (*type == 0)
{
#ifdef VMS
/* remove trailing '.' */
if (0 != (vmsn = strlen(libfsl)))
{
vmsn--;
if (libfsl[vmsn] == '.') libfsl[vmsn] = 0;
}
#endif
strcat(libfsl, ".sl");
strcpy(libfslc, libfsl);
strcat(libfslc, "c");
if (file_time_cmp(libfslc, libfsl) > 0) libf = libfslc; else libf = libfsl;
}
else libf = libfsl;
vp = vopen(libf, VFILE_BUF_SIZE, VFILE_TEXT);
if ((vp != NULL) || (*libp == 0)) break;
}
if (Batch != 2)
{
sprintf(buff, "loading %s", libf);
flush_message(buff);
}
return (vp);
}
static int jed_close_object(SLang_Load_Type *x)
{
switch (x->type)
{
case 'F': /* File */
vclose((VFILE *) x->handle);
return (1);
default: return SL_OBJ_UNKNOWN;
}
}
static char *jed_read_from_file(SLang_Load_Type *x)
{
char *s;
unsigned int n;
if ((s = vgets((VFILE *) x->handle, &n)) != NULL)
{
if (s[n - 1] != '\n') s[n] = 0;
}
return (x->buf = s);
}
static char *jed_read_from_buffer(SLang_Load_Type *x)
{
int n;
Line *l = (Line *) x->handle;
char *buf = x->buf;
if (l == NULL) return (NULL);
n = l->len;
if (n > 255) n = 255;
MEMCPY(buf, (char *) l->data, n);
buf[n] = 0;
x->handle = (long) l->next;
return(buf);
}
/* returns 0 if successful */
static int jed_open_object(SLang_Load_Type *x)
{
switch (x->type)
{
case 'F': /* File */
x->read = jed_read_from_file;
if (0 == (x->handle = (long) jed_open_lib_file((char *) x->name)))
{
return (SL_OBJ_NOPEN);
}
x->buf = (long) NULL;
x->n = 0;
return (0);
case 'B': /* Buffer */
x->read = jed_read_from_buffer;
x->handle = (long) (((Buffer *) (x->name))->beg);
return (0);
default: return SL_OBJ_UNKNOWN;
}
}
void load_buffer()
{
SLang_Load_Type x;
Buffer *cbuf = CBuf;
int flags = CBuf->flags;
char buf[256];
Line *l, *lwant;
cbuf->flags |= READ_ONLY;
x.name = (long) cbuf;
x.type = 'B';
x.buf = buf;
SLang_load_object(&x);
if (SLang_Error || *Error_Buffer)
{
SLang_doerror(NULL);
pop_to_buffer(cbuf->name);
/* if (x.ptr != NULL)
{ */
lwant = (Line *) x.handle;
if (lwant != NULL)
{
bob();
while (1)
{
l = CLine->next;
if ((l == NULL) || (l == lwant)) break;
CLine = l; LineNum++;
}
}
else eob();
Point = x.ofs;
/* Point = (int) (x.ptr - buf); */
if ((Point >= 0) && (Point < CLine->len))
{
(void) skip_whitespace();
}
else Point = 0;
/* } */
}
cbuf->flags = flags;
}
void get_key_function()
{
char *s;
int kind;
s = find_key(&kind);
if (s != NULL)
{
if (SLKeyBoard_Quit && (SLang_Error == USER_BREAK))
{
SLang_Error = 0;
SLKeyBoard_Quit = 0;
/* s = "kbd_quit"; */
}
SLang_push_integer(kind);
}
else s = "";
SLang_push_string(s);
}
static SLang_Name_Type *Expand_File_Hook;
void set_expansion_hook (char *s)
{
if (NULL == (Expand_File_Hook = SLang_get_function (s)))
{
msg_error ("The expansion hook has not been defined.");
}
}
int mini_complete (void)
{
char *pl, *pb;
char last[256], buf[256], *tmp;
static char prev[256];
int n, last_key_char = SLang_Last_Key_Char;
static int flag = 0; /* when flag goes 0, we call open */
if (complete_open == NULL) return ins_char_cmd();
Point = 0;
push_mark();
eob();
if (NULL == (tmp = make_buffer_substring(&n))) return(1);
safe_strcpy(buf, tmp, sizeof (buf));
SLFREE(tmp);
if ((last_key_char == ' ') && ((long) Last_Key_Function == (long) mini_complete))
{
if (!flag || !(flag = (*complete_next)(buf)))
{
safe_strcpy(buf, prev, sizeof (buf));
flag = (*complete_open)(buf);
}
strcpy(last, buf);
n = -1;
}
else
{
n = 0;
strcpy(prev, buf); /* save this search context */
}
if (!n)
{
if ((Repeat_Factor != NULL)
|| (complete_open != sys_findfirst) || (Expand_File_Hook == NULL))
flag = (*complete_open)(buf);
else
{
int do_free;
SLang_push_string (buf);
SLexecute_function (Expand_File_Hook);
if (SLang_Error == 0) SLang_pop_integer (&do_free);
if (SLang_Error == 0)
{
if (do_free == 0)
{
flag = (*complete_open) (buf);
goto start_loop;
}
}
if (SLang_Error || SLang_pop_string (&tmp, &do_free))
{
msg_error ("Error encounter during expansion. Disabling expansion hook.");
Expand_File_Hook = NULL;
return 1;
}
safe_strcpy (last, tmp, sizeof (last));
strcpy (prev, last);
if (do_free) SLFREE (tmp);
n = -1;
}
}
start_loop:
if (!n && flag)
{
strcpy(last, buf);
/* This do loop tests all values from complete_next and returns the
smallest length match of initial characters of buf */
do
{
if ((n == 0) && (last_key_char == '\t'))
{
set_buffer (Completion_Buffer);
erase_buffer ();
CBuf->flags |= BURIED_BUFFER;
insert_string ("!!! Use Page Up/Down keys to scroll this window. !!!\n");
}
n++;
pl = last;
pb = buf;
#ifdef __os2__
if (complete_open == open_bufflist)
while (*pl && (tolower(*pl) == tolower(*pb))) pl++, pb++;
else /* next statement */
#endif
while (*pl && (*pl == *pb)) pl++, pb++;
*pl = 0;
if (last_key_char == '\t')
{
while (*pb) pb++;
quick_insert ((unsigned char *)buf, (int) (pb - buf));
newline ();
}
}
while(0 != (flag = (*complete_next)(buf)));
#ifdef __os2__
/* OS/2 uses case-insensitive search on buffer-names. Set the
* flag if there is an exact match, so that completion will
* cycle without repeats through all the matches. */
if (complete_open == open_bufflist)
{
strcpy(buf, last);
(*complete_open)(buf);
do
{
if (!strcmp(buf, last))
{
flag = 1; break;
}
}
while ((*complete_next)(buf));
}
#endif
}
if ((n > 1) && (last_key_char == '\t') && (Last_Completion_Buffer == NULL))
{
Last_Completion_Windows = num_windows () - 1; /* not including mini */
Last_Completion_Buffer = pop_to_buffer (Completion_Buffer);
bob ();
}
while ((CBuf != MiniBuffer) || !IS_MINIBUFFER) other_window ();
if (n)
{
erase_buffer();
/* strcpy(last, buf); */
insert_string(last);
if ((n == 1) && ((long) Last_Key_Function == (long) mini_complete))
message("[Sole Completion.]");
}
else msg_error("No Match!");
return(1);
}
int what_char()
{
if (eobp()) return(0);
return( (int) *(CLine->data + Point) );
}
void update_cmd(int *force)
{
if (Batch) return;
JWindow->trashed = 1;
update((Line *) NULL, *force, 0);
}
void call_cmd(char *str)
{
int (*fp)(void);
if (NULL == (fp = (int (*)(void)) SLang_find_key_function(str, CBuf->keymap)))
{
msg_error("Function does not exist!");
}
else (void) (*fp)();
}
void copy_region_cmd(char *name)
{
Buffer *buf;
if (NULL != (buf = find_buffer(name)))
{
copy_region_to_buffer(buf);
}
else msg_error("Unable to find buffer.");
}
#ifndef pc_system
void screen_w80()
{
tt_narrow_width();
change_screen_size(80, *tt_Screen_Rows);
}
void screen_w132()
{
tt_wide_width();
change_screen_size(132, *tt_Screen_Rows);
}
#endif
char *make_line_string(char *string)
{
unsigned char *tmp, *p1, *p2;
int n;
if (CBuf->marks == NULL)
{
p1 = CLine->data + Point;
p2 = CLine->data + CLine->len;
}
else
{
p1 = CLine->data + CBuf->marks->point;
p2 = CLine->data + Point;
if (p2 < p1)
{
tmp = p1; p1 = p2; p2 = tmp;
}
pop_mark(&Number_Zero);
}
n = (int) (p2 - p1);
if (n > 254) n = 254;
MEMCPY(string, (char *) p1, n);
string[n] = 0;
return(string);
}
char *make_buffer_substring(int *np)
{
Line *tthis, *beg;
int n = 1, dn, thisp;
unsigned char *buf;
if (!check_region(&n)) return (NULL); /* spot pushed */
/* Point now at end of the region */
beg = tthis = CBuf->marks->line;
thisp = CBuf->marks->point;
n = 0;
pop_mark(&n);
while (tthis != CLine)
{
n += tthis->len;
tthis = tthis->next;
}
n -= thisp;
n += Point;
if (NULL == (buf = (unsigned char *) SLMALLOC(n + 1)))
{
msg_error("Malloc Error");
pop_spot();
return (NULL);
}
if (CLine == (tthis = beg))
{
MEMCPY((char *)buf, (char *) (tthis->data + thisp), n);
}
else
{
n = 0;
while (tthis != CLine)
{
dn = tthis->len - thisp;
MEMCPY((char *)(buf + n), (char *) (tthis->data + thisp), dn);
tthis = tthis->next;
thisp = 0;
n += dn;
}
MEMCPY((char *)(buf + n), (char *) tthis->data, Point);
n += Point;
}
buf[n] = 0;
*np = n;
pop_spot();
return ((char *) buf);
}
void buffer_substring()
{
char *buf;
int n;
if (NULL == (buf = make_buffer_substring(&n))) return;
SLang_push_malloced_string((char *)buf);
}
int markp(void)
{
return (CBuf->marks != NULL);
}
int dup_mark(void)
{
if (CBuf->marks == NULL) return(0);
push_spot();
goto_mark(CBuf->marks);
push_mark();
pop_spot();
return(1);
}
void mini_read(char *prompt, char *def, char *stuff)
{
char *buf;
int n;
complete_open = NULL;
if (NULL == (buf = read_from_minibuffer(prompt, def, stuff, &n)))
SLang_push_string ("");
else SLang_push_malloced_string(buf);
}
void get_buffer_info(void)
{
SLang_push_string(CBuf->file);
SLang_push_string(CBuf->dir);
SLang_push_string(CBuf->name);
SLang_push_integer(CBuf->flags);
}
void set_buffer_info(char *file, char *dir, char *name, int *flags)
{
safe_strcpy(CBuf->file, file, sizeof (CBuf->file));
/* I have to handle this in this way because expand_filename does not modify
* its argument.
*/
safe_strcpy(CBuf->dir, dir, sizeof (CBuf->dir));
fixup_dir(CBuf->dir);
strcpy (CBuf->dir, expand_filename (CBuf->dir));
safe_strcpy(CBuf->name, name, sizeof (CBuf->name));
CBuf->flags = *flags;
}
void make_buffer_list(void)
{
int n = 0;
Buffer *b;
b = CBuf;
do
{
SLang_push_string(b->name);
b = b->next;
n++;
}
while (b != CBuf);
SLang_push_integer(n);
}
int window_size_intrinsic(int *what)
{
register int n = 0;
switch (*what)
{
case 'r': n = JWindow->rows; break;
case 'c': n = JWindow->column; break;
case 't': n = JWindow->top; break;
case 'w': n = JWindow->width; break;
default: SLang_Error = UNKNOWN_ERROR;
}
return (n);
}
int what_mode(void)
{
SLang_push_string (CBuf->mode_str);
return CBuf->modes;
}
/* Given a file name with wildcards return expanded list to S-Lang stack
* with number. This does NOT work on unix with wild cards. Instead the
* expansion is file* (completion) */
int expand_wildcards(char *file)
{
char buf[256];
int n = 0;
safe_strcpy(buf, file, sizeof (buf));
if (sys_findfirst(buf))
{
do
{
n++;
SLang_push_string(buf);
}
while (sys_findnext(buf));
}
return (n);
}
static void jed_traceback(char *s)
{
char *n;
if (!Batch)
{
n = CBuf->name;
set_buffer("*traceback*");
eob();
insert_string(s);
set_buffer(n);
}
else fprintf(stderr, s);
}
#if 0
static struct
{
int depth = 0;
char *name[20];
int marks[20];
}
FName_Stack;
void enter_function(char *name)
{
if (depth > 20)
{
msg_error("Function Stack too deep.");
return;
}
FName_Stack->name[depth] = name;
FName_Stack->marks[depth] = 0;
}
void exit_function(char *name)
{
int n = FName_Stack->marks[depth];
}
#endif
#if 0
void make_istring(char *buf, int i)
{
register char *b, *b1, ch;
int sign, d;
b = buf;
if (i >= 0)
{
sign = 1;
}
else
{
sign = -1;
i = -i;
}
do
{
d = i % 10;
i = i / 10;
*b++ = d + '0';
}
while (i > 0);
if (sign == -1) *b++ = '-';
*b-- = 0;
b1 = buf;
/* now reverse it */
while (b > b1)
{
ch = *b;
*b-- = *b1;
*b1++ = ch;
}
}
#include <stdarg.h>
char *simple_sprintf(char *str, char *fmt, ...)
{
va_list ap;
register char ch, *s = str, *string;
char *fmtmax = fmt + strlen(fmt);
int dig;
char buf[80];
va_start(ap, fmt);
while (fmt < fmtmax)
{
ch = *fmt++;
switch(ch)
{
case '%': ch = *fmt++;
string = buf;
switch(ch)
{
case 'c': ch = (char) va_arg(ap, int); /* drop */
case '%': buf[0] = ch; buf[1] = 0; break;
case 's':
string = va_arg(ap, char *); break;
case 'l':
case 'd':
default:
dig = va_arg(ap, int);
make_istring(buf, dig);
break;
}
while (*string) *s++ = *string++;
break;
case '\\':
ch = *fmt++;
switch(ch)
{
case 'b': ch = '\b'; break;
case 'r': ch = 13; break;
case 'n': ch = '\n'; break;
case 'e': ch = 27; break;
case 'a': ch = 7; break;
}
/* drop */
default:
*s++ = ch;
}
}
va_end(ap);
*s = 0;
return(str);
}
#endif
char *command_line_argv(int *nn)
{
int n = *nn;
if ((n >= Main_Argc) || (n < 0))
{
msg_error("Argc out of bounds.");
n = 0;
}
return Main_Argv[n];
}
void count_chars(void)
{
unsigned long n = 0, m = 0;
int ch;
char buf[64];
Line *l = CBuf->beg;
while (l != NULL)
{
n += l->len;
l = l->next;
}
l = CBuf->beg;
while (l != CLine)
{
m += l->len;
l = l->next;
}
m += Point + 1;
ch = eobp() ? 0 : (int) *(CLine->data + Point);
sprintf(buf, "'@'=%d/0x%x/%#o, point %lu of %lu", ch, ch, ch, m, n);
if (ch != 0) buf[1] = ch;
else buf[0] = '^';
SLang_push_string(buf);
}
static void jed_clear_error(void)
{
*Error_Buffer = 0;
SLKeyBoard_Quit = 0;
}
int (*X_Init_SLang_Hook)(void);
void init_minibuffer()
{
Buffer *tmp;
tmp = CBuf;
The_MiniBuffer = make_buffer();
The_MiniBuffer->modes = 0;
strcpy(The_MiniBuffer->name, " <mini>");
/* do some initializing */
switch_to_buffer(The_MiniBuffer);
remake_line(132);
The_MiniWindow = create_window(*tt_Screen_Rows, 1, 1, *tt_Screen_Cols);
The_MiniWindow->buffer = CBuf;
Buffer_Local.tab = 0;
switch_to_buffer(tmp);
SLang_Dump_Routine = jed_traceback;
#ifdef __GO32__
SLang_Interrupt = i386_check_kbd;
#endif
#if 0
SLang_Enter_Function = enter_function;
SLang_Exit_Function = exit_function;
#endif
if (!init_SLang()
#ifdef FLOAT_TYPE
|| !init_SLmath()
#endif
#ifndef pc_system
#ifdef unix
|| !init_SLunix()
#endif
#endif
|| !init_jed_intrinsics()
|| !register_jed_classes ()
|| ((X_Init_SLang_Hook != NULL) && !(*X_Init_SLang_Hook)()))
{
exit_error("Unable to initialize S-Lang!", 0);
}
/* use jed rouotines instead of default slang ones */
SLang_Error_Routine = msg_error;
SLang_User_Open_Slang_Object = jed_open_object;
SLang_User_Close_Slang_Object = jed_close_object;
SLang_User_Clear_Error = jed_clear_error;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.