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.