home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / ledit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  35.8 KB  |  1,891 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include <string.h>
  7.  
  8. #include "config.h"
  9. #ifdef pc_system
  10. # include <fcntl.h>
  11. #endif
  12.  
  13. #include "buffer.h"
  14. #include "keymap.h"
  15. #include "file.h"
  16. #include "ins.h"
  17. #include "ledit.h"
  18. #include "screen.h"
  19. #include "window.h"
  20. #include "display.h"
  21. #include "search.h"
  22. #include "misc.h"
  23. #include "replace.h"
  24. #include "paste.h"
  25. #include "sysdep.h"
  26. #include "cmds.h"
  27. #include "text.h"
  28. #include "slang.h"
  29. #include "hooks.h"
  30. #define JED_PROMPT "S-Lang>"
  31.  
  32. Buffer *MiniBuffer;
  33. Buffer *Last_Buffer;
  34. char *Token_Pointer;
  35. Buffer *The_MiniBuffer;     /* this never gets deleted since we may need it */
  36. Window_Type *The_MiniWindow;
  37.  
  38. extern char *get_cwd(void);
  39. int Ignore_Beep = 0;
  40. int MiniBuffer_Active = 0;
  41.  
  42. User_Variable_Type User_Vars =
  43.   {
  44.       78,                /* wrap-column */
  45.       8,                /* tabs */
  46.       3,                /* c_indent */
  47.       2,                /* c_brace */
  48.      300,                /* max_hits */
  49.   };
  50.  
  51. char Last_Search_Str[132];
  52. #ifdef pc_system
  53. char Jed_Library[256];
  54. #else
  55. char Jed_Library[1024];
  56. #endif
  57.  
  58. int (*complete_open)(char *);
  59. int (*complete_next)(char *);
  60. static int Buf_List_Len;
  61. Buffer *Buf_Context;
  62.  
  63. static char *Expect_File_Error = "Expecting filename.";
  64. static char *Keymap_Error = "Unknown_Keymap";
  65.  
  66. /* read doc file */
  67. int get_doc_string(char *f, char *file)
  68. {
  69.    char *buf, *b, *f1;
  70.    VFILE *fp;
  71.    int ret = 0;
  72.    unsigned int n;
  73.    char newline = 1;               /* ascii value of line term (^A) */
  74.    
  75.    if (*f == 0) return(0);
  76.  
  77.    if ((fp = vopen(file, 1024, VFILE_TEXT)) == NULL) return(0);
  78.    
  79.    while ((buf = vgets(fp, &n)) != NULL)
  80.      {
  81.     f1 = f; b = buf;
  82.     while (*f1 && (*f1 == *b)) f1++, b++;
  83.     if (*f1) continue;
  84.     
  85.     b = buf;
  86.     b[n - 1] = 0;
  87.     
  88.     while (*b)
  89.       {
  90.          if (*b == newline) *b = '\n';
  91.          b++;
  92.       }
  93.     
  94.     SLang_push_string(buf + 1);   /* lose the prefix */
  95.     ret = 1;
  96.     break;
  97.      }
  98.    vclose(fp);
  99.    return(ret);
  100. }
  101.  
  102. int next_bufflist(char *buf)
  103. {
  104.    Buffer *tthis;
  105.    while (1)
  106.      {
  107.     tthis = Buf_Context;
  108.     if (tthis == MiniBuffer) return(0);
  109.     Buf_Context = Buf_Context->next;
  110. #ifdef __os2__
  111.      if (!Buf_List_Len || !strncmpi(buf, tthis->name, Buf_List_Len))
  112. #else
  113.       if (!Buf_List_Len || !strncmp(buf, tthis->name, Buf_List_Len))
  114. #endif
  115.       {
  116.          if (*tthis->name == ' ') continue;   /* internal buffers */
  117.          strcpy(buf, tthis->name);
  118.          return(1);
  119.       }
  120.      }
  121. }
  122.  
  123. int open_bufflist(char *buf)
  124. {
  125.    if ((Buf_Context = MiniBuffer) == NULL) return(0);
  126.    Buf_Context = Buf_Context->next;
  127.    Buf_List_Len = strlen(buf);
  128.    return next_bufflist(buf);
  129. }
  130.  
  131. char *what_buffer()
  132. {
  133.    return(CBuf->name);
  134. }
  135.  
  136. int bufferp(char *name)
  137. {
  138.    if (NULL == find_buffer(name)) return(0); else return(1);
  139. }
  140.  
  141. int insert_buffer_name(char *name)
  142. {
  143.    Buffer *buf;
  144.  
  145.    if (NULL != (buf = find_buffer(name)))
  146.      {
  147.     insert_buffer(buf);
  148.     return(1);
  149.      }
  150.    else msg_error("Unable to find buffer.");
  151.    return(0);
  152. }
  153.  
  154. int replace_cmd(char *old, char *neew)
  155. {
  156.    int n = 0;
  157.    
  158.    CHECK_READ_ONLY
  159.    push_spot ();
  160.    if (search(old, 1, 0)) while(replace_next(old, neew)) n++;
  161.    pop_spot();
  162.    return n;
  163. }
  164.  
  165. int kill_buffer_cmd(char *name)
  166. {
  167.    Buffer *this_buf, *kill_buf, *scratch, *buf;
  168.    Window_Type *w;
  169.    int kill;
  170.  
  171.    if (NULL == (kill_buf = find_buffer(name)))
  172.      {
  173.     msg_error("Buffer does not exist.");
  174.     return(0);
  175.      }
  176.    
  177.    this_buf = CBuf;
  178.    switch_to_buffer(kill_buf);
  179.    
  180.    kill = 1;
  181.    if ((*name != ' ') && (kill_buf->flags & BUFFER_TRASHED))
  182.      {
  183.     flush_message("Buffer modified. Kill, Save First, Abort: [KSA]");
  184.     /* This does not go through keyboard macro routines
  185.        on purpose! */
  186.     switch (my_getkey())
  187.       {
  188.          case 'k': case 'K': kill = 1; break;
  189.          case 's': case 'S': kill = 2; break;
  190.          default: msg_error("Aborted."); return(0);
  191.       }
  192.     message("");
  193.      }
  194.  
  195.    if (kill == 2)
  196.      {
  197.     write_buffer();
  198.     if (SLang_Error) 
  199.       {
  200.          switch_to_buffer(this_buf);
  201.          return(0);
  202.       }
  203.      }
  204.    
  205.    /* if it is the scratch buffer, just erase it since we are going to 
  206.       recreate it anyway. */
  207.    
  208.    scratch = find_buffer("*scratch*");
  209.    if (kill_buf == scratch)
  210.      {
  211.     erase_buffer();
  212.     switch_to_buffer(this_buf);
  213.     return(1);
  214.      }
  215.  
  216.    if (NULL == scratch)
  217.      {
  218.     scratch = make_buffer();
  219.     strcpy(scratch->name, "*scratch*");
  220.     strcpy(scratch->dir, CBuf->dir);
  221.     *scratch->file = 0;
  222.      }
  223.  
  224.    /* find a buffer to replace this one with if it is in a window */
  225.    if (buffer_visible(kill_buf))
  226.      {
  227.     buf = kill_buf->next;
  228.     while((buf != kill_buf) && 
  229.           ((*buf->name == ' ') || (buf->flags & BURIED_BUFFER)
  230.            || (buf == scratch) || (buffer_visible(buf))))
  231.       {
  232.          buf = buf->next;
  233.       }
  234.     if (buf == kill_buf) buf = scratch;
  235.  
  236.     /* search through windows looking for the buffer and replace it */
  237.     w = JWindow;
  238.     do
  239.       {
  240.          if (kill_buf == JWindow->buffer)
  241.            {
  242.           touch_window_hard (JWindow, 0);
  243.           window_buffer(buf);  /* I should choose a different one
  244.                     every time */
  245.            }
  246.          JWindow = JWindow->next;
  247.       }
  248.     while (w != JWindow);
  249.      }
  250.    else buf = scratch;
  251.    if (kill_buf == Last_Buffer) Last_Buffer = NULL;   
  252.    if (kill_buf == this_buf) this_buf = buf;
  253.    switch_to_buffer(this_buf);
  254.    delete_buffer(kill_buf);
  255.    return(1);
  256. }
  257.  
  258. int write_buffer_cmd(char *filestr)
  259. {
  260. #ifdef VMS
  261.    char *ff;
  262. #endif
  263.    char dir[256], *f, file[256];
  264.    char msgstr[132];
  265.    int n;
  266.  
  267. #ifdef unix
  268. #ifndef __GO32__
  269.    f = expand_link(filestr);
  270. #else
  271.    f = expand_filename(filestr);
  272. #endif
  273. #else
  274.    f = expand_filename(filestr);
  275. #endif
  276.    
  277.    strcpy(file, f);
  278.    f = extract_file(file);
  279.  
  280.    if ((*f == 0) && (*CBuf->file == 0))
  281.      {
  282.     msg_error("Filename Required.");
  283.     return(0);
  284.      }
  285.    
  286.    n = (int) (f - file);
  287.    MEMCPY((char *) dir, (char *) file, n);
  288.    dir[n] = 0;
  289.    
  290.    if (*f == 0) f = CBuf->file;
  291.  
  292.    n = write_file_with_backup(dir, f);
  293.    if (n >= 0)
  294.      {
  295. #ifdef VMS
  296.     ff = f; while (*ff) if (*ff == ';') *ff = 0; else ff++;
  297. #endif
  298.     sprintf(msgstr,"Wrote %d lines to %s%s", n, dir, f);
  299.     message(msgstr);
  300.     CBuf->flags &= ~BUFFER_TRASHED;
  301.     CBuf->flags |= AUTO_SAVE_BUFFER;
  302.     CBuf->hits = 0;
  303.     visit_file(dir, f);
  304.     return(1);
  305.      }
  306.    else
  307.      {
  308.     sprintf(msgstr,"Error writing file %s%s", dir, f);
  309.     msg_error(msgstr);
  310.     return(0);
  311.      }
  312. }
  313.  
  314. #if defined(msdos) && !defined(__WATCOMC__)
  315. int show_memory()
  316. {
  317.    struct farheapinfo hi;
  318.    char buf[132];
  319.    char *c;
  320.    unsigned long total = 0, core, used = 0;
  321.    unsigned long max = 0;
  322.    int i = 0;
  323.    
  324.    hi.ptr = NULL;
  325.    if (farheapcheck() == _HEAPCORRUPT) c = "corrupt"; else c = "ok";
  326.    while (farheapwalk(&hi) == _HEAPOK)
  327.      {
  328.     if (hi.in_use)
  329.       used += hi.size;
  330.     else 
  331.       {
  332.          total += hi.size;
  333.          if (hi.size > max) max = hi.size;
  334.          i++;
  335.       }
  336.      }
  337.    core = farcoreleft();
  338.    sprintf(buf, "used:%lu, core:%lu, free:%lu, grand:%lu, max:%lu, frag:%d (%s)",
  339.        used, core, total, core + total, max, i, c);
  340.    message(buf);
  341.    return (0);
  342. }
  343. #endif
  344.  
  345. #ifdef __WATCOMC__
  346. #include <malloc.h>
  347. int show_memory()
  348. {
  349.    char buf[132];
  350.    unsigned long mem = _memavl();
  351.    
  352.    sprintf(buf, "avail mem: %lu, tot phys pgs: ???, free lin space: ???",
  353.        mem);
  354.  
  355.    message(buf);
  356.    return (0);
  357. }
  358. #endif
  359.  
  360. #ifdef __GO32__
  361. #include <dpmi.h>
  362.  
  363. int show_memory()
  364. {
  365.    char buf[132];
  366.    unsigned long mem;
  367.    _go32_dpmi_meminfo info;
  368.    
  369.    _go32_dpmi_get_free_memory_information(&info);
  370.    
  371.    if (info.available_physical_pages != -1)
  372.      mem = info.available_physical_pages * 4096;
  373.    else mem = info.available_memory;
  374.    
  375.    sprintf(buf, "avail mem: %lu, tot phys pgs: %lu, free lin space: %lu",
  376.        mem, info.total_physical_pages, info.free_linear_space);
  377.  
  378.    message(buf);
  379.    return (0);
  380. }
  381. #endif
  382.  
  383. int set_buffer(char *name)
  384. {
  385.     Buffer *buf;
  386.  
  387.     if ((name == NULL) || (*name == 0))
  388.      {
  389.     msg_error("set_buffer: Buffer name is NULL");
  390.     return (0);
  391.      }
  392.    
  393.     /* Last_Buffer = CBuf; */
  394.  
  395.     if (NULL == (buf = find_buffer(name)))
  396.       {
  397.      buf = make_buffer();
  398.      strcpy(buf->dir, CBuf->dir);
  399.      *buf->file = 0;
  400.      switch_to_buffer(buf);
  401.      uniquely_name_buffer(name);
  402.       }
  403.     else switch_to_buffer(buf);
  404.     return(1);
  405. }
  406.  
  407. int get_yes_no(char *question)
  408. {
  409.    char buf[256], *tmp;
  410.    int n; 
  411.    
  412.    strcpy(buf, question);
  413.    strcat(buf, "? (yes or no)");
  414.  
  415.    while(1)
  416.      {
  417.     if (NULL == (tmp = read_from_minibuffer(buf, 0, NULL, &n))) return(-1);
  418.     
  419.     if (!strcmp(tmp, "yes"))
  420.       {
  421.          SLFREE(tmp);
  422.          return(1);
  423.       }
  424.     
  425.     if (!strcmp(tmp, "no"))
  426.       {
  427.          SLFREE(tmp);
  428.          return(0);
  429.       }
  430.     msg_error("yes or no!");
  431.     SLFREE(tmp);
  432.      }
  433. }
  434.  
  435. int find_file_cmd(char *filestr)       /* filestr is const ! */
  436. {
  437.    char *f, *file, filebuf[256];
  438.    char msgstr[132];
  439.    Buffer *buf;
  440.    int n;
  441.  
  442. #ifdef unix
  443. #ifndef __GO32__
  444.    file = expand_link(filestr);
  445. #else
  446.    file = expand_filename(filestr);
  447. #endif
  448. #else
  449.    file = expand_filename(filestr);
  450. #endif
  451.  
  452.    strcpy(filebuf, file);
  453.    file = filebuf;
  454.    f = extract_file(file);
  455.    if ((*file == 0) || (*f == 0))
  456.      {
  457.     msg_error(Expect_File_Error);
  458.     return(0);
  459.      }
  460.  
  461.    /* search for the file in current buffer list */
  462.  
  463.    if (NULL != (buf = find_file_buffer(file)))
  464.      {
  465.     if (file_changed_on_disk(file))
  466.       {
  467.          if (get_yes_no("File changed on disk.  Read From Disk"))
  468.            {
  469.           if (*Error_Buffer) return(1);
  470.           n = (int) LineNum;
  471.           buf->flags  &= ~BUFFER_TRASHED;
  472.           kill_buffer_cmd(buf->name);
  473.           find_file_cmd(file);
  474.           goto_line(&n);
  475.           return(1);
  476.            }
  477.       }
  478.  
  479.     switch_to_buffer (buf);
  480.     return(1);
  481.      }
  482.  
  483.    buf = make_buffer();
  484.    switch_to_buffer(buf);
  485.    buffer_filename(file, NULL);
  486.       
  487.    n = read_file(file);
  488.    CLine = CBuf->beg;
  489.    Point = 0;
  490.    LineNum = 1;
  491.    if (CLine == NULL) make_line(25);
  492.    set_file_modes();
  493.    CBuf->flags |= UNDO_ENABLED;
  494.  
  495.    switch(n)
  496.      {
  497.       case -2: msg_error("File not readable."); break;
  498.       default: 
  499.     if (Batch == 2) break;
  500.     if (*Message_Buffer) break;   /* autosave warning? */
  501.     if (n == -1) message("New file.");
  502.     else 
  503.       {
  504.          sprintf(msgstr,"%d lines read", n);
  505.          message(msgstr);
  506.       }
  507.      }
  508.       
  509.    SLang_run_hooks("find_file_hook", file, NULL); 
  510.    return(1);
  511. }
  512.  
  513. int find_file_in_window(char *file)
  514. {
  515.    int ret;
  516.    Buffer *b = CBuf;
  517.    
  518.    ret = find_file_cmd(file);
  519.    if ((b != CBuf) && (*CBuf->name != ' ')) Last_Buffer = CBuf;
  520.    window_buffer(CBuf);
  521.    return(ret);
  522. }
  523.  
  524. #if 0
  525. removed to S-Lang functions
  526.  
  527. int do_search_cmd(int d)
  528. {
  529.  
  530.    char *s, *p, *tmp, *str = Last_Search_Str;
  531.    int n;
  532.  
  533.    complete_open = NULL;
  534.  
  535.     if (d == 1) p = "Search:"; else p = "Search backward:";
  536.     if (*str == 0) s = NULL; else s = str;
  537.     if (NULL == (tmp = read_from_minibuffer(p, s, NULL, &n))) return(0);
  538.  
  539.     if (*tmp) 
  540.      {
  541.     strcpy(str, tmp);
  542.     if (d == 1) forwchars(&Number_One);
  543.     if (search(str, d, 0)) 
  544.       {
  545.          SLFREE(tmp);
  546.          return(1);
  547.       }
  548.     if (d == 1) backwchars(&Number_One);
  549.    
  550.     /* I prefer having this generate an error since keyboard Macro will
  551.        abort. */
  552.     msg_error("Not Found!");
  553.      }
  554.    SLFREE(tmp);
  555.    return(0);
  556. }
  557.  
  558. int search_forward_cmd()
  559. {
  560.    return do_search_cmd(1);
  561. }
  562.  
  563. int search_backward_cmd()
  564. {
  565.    return do_search_cmd(-1);
  566. }
  567.  
  568. #endif
  569. void set_mode_cmd(char *mode, int *flags)
  570. {
  571.    char *m = CBuf->mode_str;
  572.    CBuf->modes = *flags;
  573.    strncpy((char *) m, (char *) mode, 12);
  574.    m[12] = 0;
  575. }
  576.  
  577.  
  578.  
  579. /* create a minibuffer with window and switch to it. */
  580. void create_minibuffer(void)
  581. {
  582.    Window_Type *w;
  583.    MiniBuffer = The_MiniBuffer;
  584.    
  585.    /* I want to make Mini_Window->next = Current Window so that scroll other
  586.       window routines will scroll it. */
  587.  
  588.    w = JWindow;
  589.    do other_window(); while (JWindow->next != w);
  590.    JWindow->next = The_MiniWindow;
  591.    The_MiniWindow->next = w;
  592.    The_MiniWindow->column = 1;
  593.    Mini_Info.action_window = w;
  594.    other_window();    /* now in minibuffer window */
  595.    window_buffer(MiniBuffer);
  596.    switch_to_buffer(MiniBuffer);
  597.    MiniBuffer_Active = 1;
  598.    erase_buffer ();
  599.    /* allow kill region to kill to beginning of minibuffer. 
  600.     * Suggested by stefen@uni-paderborn.de */
  601.    push_mark ();               
  602. }
  603.  
  604. char *Completion_Buffer = "*Completions*";
  605.  
  606. static char *Last_Completion_Buffer;
  607. static int Last_Completion_Windows;
  608.  
  609. /* evaluate command in minibuffer and leave */
  610. int exit_minibuffer()
  611. {
  612.    if (IS_MINIBUFFER)
  613.      {
  614.     if (Last_Completion_Buffer != NULL)
  615.       {
  616.          pop_to_buffer (Completion_Buffer);
  617.          CBuf->flags &= ~BUFFER_TRASHED;
  618.          switch_to_buffer_cmd (Last_Completion_Buffer);
  619.          kill_buffer_cmd (Completion_Buffer);
  620.          touch_window_hard (JWindow, 0);
  621.          if (Last_Completion_Windows == 1) one_window ();
  622.       }
  623.         select_minibuffer ();
  624.     Exit_From_MiniBuffer = 1;
  625.      }
  626.    Last_Completion_Buffer = NULL;
  627.    return(0);
  628. }
  629.  
  630. /* return 1 if minibuffer already exists otherwise returns 0 */
  631. int select_minibuffer()
  632. {
  633.     Window_Type *w;
  634.  
  635.     /* Try to find active minibuffer and go there */
  636.     w = JWindow;
  637.     while (MiniBuffer != NULL)
  638.       {
  639.      if (JWindow->top == *tt_Screen_Rows) return(1);
  640.      other_window();
  641.      if (w == JWindow) exit_error("Internal Error:  no window!", 1);
  642.       }
  643.  
  644.     /* switchs to minibuffer too */
  645.     create_minibuffer();
  646.     return(0);
  647. }
  648.  
  649. /* if cmd != NULL, insert it into minibuffer and then send the result to
  650.    the appropriate routine. */
  651.  
  652. int ledit(void)
  653. {
  654.    int n;
  655.    char *tmp;
  656.    
  657.    if (MiniBuffer == NULL) complete_open = NULL;
  658.    if (NULL == (tmp = read_from_minibuffer(JED_PROMPT, 0, NULL, &n))) return(0);
  659.    SLang_Error = 0;
  660.    Suspend_Screen_Update = 1;
  661.    
  662.    SLang_load_string(tmp);
  663.    SLFREE(tmp);
  664.    
  665.    if ((SLang_Error == -1) && SLKeyBoard_Quit)
  666.      {
  667.     msg_error("Quit!");
  668.      }
  669.    SLang_Error = 0;
  670.  
  671.    return(1);
  672. }
  673.  
  674. char *read_file_from_minibuffer(char *prompt, char *def)
  675. {
  676.    int n;
  677.    char buf[256];
  678.    
  679.    complete_open = sys_findfirst;
  680.    complete_next = sys_findnext;
  681.  
  682.    if (*CBuf->dir == 0) strcpy(CBuf->dir, get_cwd());
  683.    strcpy(buf, CBuf->dir);
  684.    return read_from_minibuffer(prompt, def, buf, &n);
  685. }
  686.  
  687. static char *String_Completion_Str;
  688. static char *String_Completion_Str_Next;
  689. static int String_Completion_Str_Len;
  690.  
  691.  
  692. static int next_string_list (char *buf)
  693. {
  694.    register char *s = String_Completion_Str_Next;
  695.    int len;
  696.    while (*s)
  697.      {
  698.     while (*s && (*s != ',')) s++;
  699.     len = (int) (s - String_Completion_Str_Next);
  700.     
  701.     if (*s == ',') s++;
  702.     
  703.     if (!len 
  704.         || strncmp (buf, String_Completion_Str_Next, String_Completion_Str_Len))
  705.       {
  706.          String_Completion_Str_Next = s;
  707.          continue;
  708.       }
  709.     if (len > 255) len = 255;
  710.     strncpy (buf, String_Completion_Str_Next, len);
  711.     buf[len] = 0;
  712.     String_Completion_Str_Next = s;
  713.     return 1;
  714.      }
  715.    String_Completion_Str_Next = s;
  716.    return 0;
  717. }
  718.  
  719. static int open_string_list (char *buf)
  720. {
  721.    String_Completion_Str_Next = String_Completion_Str;
  722.    String_Completion_Str_Len = strlen (buf);
  723.    return next_string_list (buf);
  724. }
  725.  
  726.  
  727. void read_object_with_completion(char *prompt, char *dflt, char *stuff, int *typep)
  728. {
  729.    int type = *typep, n;
  730.    char buf[256], *tmp;
  731.    char *str = NULL;
  732.    int dofree = 0;
  733.    
  734.    *buf = 0;
  735.    if (type == 'f')               /* file */
  736.      {
  737.     complete_open = sys_findfirst;
  738.     complete_next = sys_findnext;
  739.     if (*CBuf->dir == 0) strcpy(CBuf->dir, get_cwd());
  740.     strcpy(buf, CBuf->dir);
  741.      }
  742.    else if (type == 'b')           /* buffer */
  743.      {
  744.     complete_open = open_bufflist;
  745.     complete_next = next_bufflist;
  746.      }
  747.    else if (type == 'F')           /* function */
  748.      {
  749.     complete_open = open_function_list;
  750.     complete_next = next_function_list;
  751.      }
  752.    else if (type == 's')
  753.      {
  754.     complete_open = open_string_list;
  755.     complete_next = next_string_list;
  756.     if (SLang_pop_string (&str, &dofree)) return;
  757.     String_Completion_Str = str;
  758.      }
  759.    else 
  760.      {
  761.     complete_open = NULL;
  762.      }
  763.    
  764.    strcat (buf, stuff);
  765.    
  766.    if (NULL != (tmp = read_from_minibuffer(prompt, dflt, buf, &n))) 
  767.      {
  768.     if (type == 'f') SLang_push_string(expand_filename(tmp));
  769.     else SLang_push_string(tmp);
  770.     
  771.     SLFREE(tmp);
  772.     
  773.     if (dofree) SLFREE (str);
  774.      }
  775. }
  776.  
  777.  
  778.  
  779. int insert_file_cmd()
  780. {
  781.    char *filebuf, *f, *file;
  782.  
  783.    CHECK_READ_ONLY
  784.    
  785.    if (NULL == (filebuf = read_file_from_minibuffer("Insert file:", NULL))) return(0);
  786.    file = expand_filename(filebuf);
  787.    SLFREE (filebuf);
  788.    f = extract_file(file);
  789.    if ((*file == 0) || (*f == 0))
  790.      {
  791.     msg_error(Expect_File_Error);
  792.     return(1);
  793.      }
  794.  
  795.    if (insert_file(file) < 0) msg_error("Error inserting file.");
  796.    return(1);
  797. }
  798.  
  799.  
  800. int find_file()
  801. {
  802.    char *tmp;
  803.    
  804.    if (NULL == (tmp = read_file_from_minibuffer("Find file:", (char *) NULL))) return(0);
  805.    find_file_in_window(tmp);
  806.    SLFREE(tmp);
  807.    return(0);
  808. }
  809.  
  810. int write_buffer()
  811. {
  812.     char *tmp;
  813.  
  814.    if (NULL == (tmp = read_file_from_minibuffer("Write to file:", (char *) NULL))) return(0);
  815.    write_buffer_cmd(tmp);
  816.    SLFREE(tmp);
  817.    return(1);
  818. }
  819.  
  820. void switch_to_buffer_cmd(char *name)
  821. {
  822.    Buffer *tthis = CBuf;
  823.    
  824.    set_buffer(name);
  825.    window_buffer(CBuf);
  826.    if ((CBuf != tthis) && (*CBuf->name != ' ')) Last_Buffer = tthis;
  827. }
  828.  
  829. void get_last_buffer(void)
  830. {
  831.    Buffer *b = CBuf->next;
  832.    
  833.    if ((Last_Buffer == NULL) || (*Last_Buffer->name == ' ')) Last_Buffer = CBuf;
  834.    
  835.    if ((*Last_Buffer->name != ' ')
  836.        && ((NULL == buffer_visible(Last_Buffer)) && (Last_Buffer != CBuf))) return;
  837.    
  838.    while (b != CBuf)
  839.      {
  840.     if ((*b->name) && (*b->name != ' ') && (NULL == buffer_visible(b)))
  841.       {
  842.          Last_Buffer = b;
  843.          return;
  844.       }
  845.     b = b->next;
  846.      }
  847.    if (Last_Buffer == NULL) Last_Buffer = find_buffer("*scratch*");
  848.    if (Last_Buffer == NULL) Last_Buffer = CBuf;
  849.    return;
  850. }
  851.  
  852. int get_buffer()
  853. {
  854.    char *tmp;
  855.    int n;
  856.    complete_open = open_bufflist;
  857.    complete_next = next_bufflist;
  858.    
  859.    get_last_buffer();
  860.  
  861.    if (NULL == (tmp = read_from_minibuffer("Switch to buffer:", Last_Buffer->name, NULL, &n))) return(0);
  862.    switch_to_buffer_cmd(tmp);
  863.    SLFREE(tmp);
  864.    return(1);
  865. }
  866.  
  867.  
  868. int kill_buffer()
  869. {
  870.    char *tmp;
  871.    int n;
  872.  
  873.    complete_open = open_bufflist;
  874.    complete_next = next_bufflist;
  875.    if (NULL == (tmp = read_from_minibuffer("Kill buffer:", (char *) CBuf->name, NULL, &n))) return(0);
  876.    kill_buffer_cmd(tmp);
  877.    SLFREE(tmp);
  878.    return(1);
  879. }
  880.  
  881. int evaluate_cmd()
  882. {
  883.     return(!ledit());
  884. }
  885.  
  886.  
  887. void insert_string(char *s)
  888. {
  889.    CHECK_READ_ONLY_VOID
  890.    ins_chars((unsigned char *) s, strlen(s));
  891. }
  892.  
  893. /* This is weird, Ultrix cc will not compile if set_key comes before unset_key */
  894.  
  895. void unset_key(char *key)
  896. {
  897.    SLang_undefine_key(key, Global_Map);
  898. }
  899.  
  900. void set_key(char *function, char *key)
  901. {
  902.    SLang_define_key(key, function, Global_Map);
  903. }
  904.  
  905. void unset_key_in_keymap(char *key, char *map)
  906. {
  907.    SLKeyMap_List_Type *kmap;
  908.  
  909.    if (NULL == (kmap = SLang_find_keymap(map)))
  910.      {
  911.     msg_error(Keymap_Error);
  912.     return;
  913.      }
  914.  
  915.    SLang_undefine_key(key, kmap);
  916. }
  917.  
  918. int keymap_p(char *name)
  919. {
  920.    return ! (NULL == SLang_find_keymap(name));
  921. }
  922.  
  923. void set_key_in_keymap(char *f, char *key, char *map)
  924. {
  925.    SLKeyMap_List_Type *kmap;
  926.  
  927.    if (NULL == (kmap = SLang_find_keymap(map)))
  928.      {
  929.     msg_error(Keymap_Error);
  930.     return;
  931.      }
  932.  
  933.    SLang_define_key(key, f, kmap);
  934. }
  935.  
  936. char *pop_to_buffer(char *name)
  937. {
  938.    Window_Type *w, *action, *use_this;
  939.    char *bname;
  940.    Line *line, *oldline;
  941.    int p, oldp, lnum, oldlnum;
  942.    Buffer *b, *oldb;
  943.    
  944.    if (!strcmp(name, " <mini>"))
  945.      {
  946.     select_minibuffer ();
  947.     return CBuf->name;
  948.      }
  949.  
  950.    /* save position so we can pop back to it if buffer already exists in 
  951.       window */
  952.    oldb = CBuf; oldline = CLine; oldp = Point; oldlnum = LineNum;
  953.    
  954.    set_buffer(name);   
  955.    line = CLine; p = Point; lnum = LineNum;
  956.    
  957.    use_this = NULL;
  958.    if (MiniBuffer != NULL)
  959.      {
  960.     action = Mini_Info.action_window;
  961.      }
  962.    else action = NULL;
  963.  
  964.    w = JWindow;
  965.    /* find a window to use */
  966.    do
  967.      {
  968.     if (w->top != *tt_Screen_Rows)
  969.       {
  970.          if (action != NULL)
  971.            {
  972.           if (w != action) use_this = w;
  973.            }
  974.          else if (w != JWindow) use_this = w;
  975.  
  976.          if (w->buffer == CBuf)
  977.            {
  978.           use_this = w;
  979.           break;
  980.            }
  981.       }
  982.     w = w->next;
  983.      }
  984.    while (w != JWindow);
  985.  
  986.    b = CBuf;
  987.    if (use_this != NULL)
  988.      {
  989.     while(JWindow != use_this) other_window();
  990.     /* This is a good reason for haveing otherwindow avoid switching buffers */
  991.     if (CBuf == oldb) 
  992.       {
  993.          CLine = oldline; Point = oldp; LineNum = oldlnum;
  994.       }
  995.      }
  996.    else
  997.      {
  998.     if (action != NULL) while(JWindow != action) other_window();
  999.     split_window();
  1000.     /* 
  1001.      * doing it this way makes screen update look better
  1002.      */
  1003.     w = JWindow; 
  1004.     do  
  1005.       {
  1006.          other_window();
  1007.       }
  1008.     while (JWindow->buffer != w->buffer);
  1009.     JWindow->column = 1;
  1010.      }
  1011.    
  1012.    bname = CBuf->name;
  1013.    switch_to_buffer(b);
  1014.    b->line = CLine = line;
  1015.    b->point = Point = p;
  1016.    b->linenum = LineNum = lnum;
  1017.    window_buffer(b);
  1018.    return bname;
  1019. }
  1020.  
  1021. /* return number of windows */
  1022. int num_windows()
  1023. {
  1024.    Window_Type *w;
  1025.    int i = 0;
  1026.  
  1027.    w = JWindow->next;
  1028.    while (i++, w != JWindow) w = w->next;
  1029.    return(i);
  1030. }
  1031.  
  1032. /* I need to make this take another parameter which indicates what to do 
  1033.    with the cursor rather than sticking it at the end.  Call the parameter p.
  1034.      Then try:
  1035.      if (p <= 0) p = strlen(Message_Buffer) + 1;
  1036.       tt_goto_rc(Screen_Height, p); */
  1037.      
  1038. void flush_message(char *m)
  1039. {
  1040.    message(m);
  1041.    if ((JScreen[0].old == NULL) || Batch) return;
  1042.    do_dialog(Message_Buffer);
  1043.    tt_goto_rc(*tt_Screen_Rows - 1, strlen(Message_Buffer));
  1044.    *Message_Buffer = 0;
  1045.    JWindow->trashed = 1;
  1046.    flush_output ();
  1047. }
  1048.  
  1049. #if defined (unix) || defined (__os2__)
  1050. # if defined (__BORLANDC__) || defined (_MSC_VER)
  1051. #   define popen _popen
  1052. #   define pclose _pclose
  1053. # endif
  1054.  
  1055. #ifndef __GO32__
  1056. static char *Process_Error = "Unable to open process.";
  1057.  
  1058. int shell_command(char *cmd)
  1059. {
  1060.    int n = 0;
  1061.    FILE *pp;
  1062.    VFILE *vp;
  1063.    
  1064.    if (NULL == (pp = popen(cmd, "r")))
  1065.      {
  1066.     msg_error(Process_Error);
  1067.     return(0);
  1068.      }
  1069.    
  1070.    if (NULL != (vp = vstream(fileno(pp), 0, VFILE_BINARY)))
  1071.      {
  1072.     n = insert_file_pointer(vp);
  1073.     if (vp->buf != NULL) SLFREE(vp->buf);
  1074.     SLFREE(vp);
  1075.      }
  1076.    else    msg_error("Malloc Error.");
  1077.     
  1078.    pclose(pp);
  1079.    return(n);
  1080. }
  1081.  
  1082. int pipe_region(char *cmd)
  1083. {
  1084.    FILE *pp;
  1085.    int n;
  1086.  
  1087.    if (NULL == (pp = popen(cmd, "w")))
  1088.      {
  1089.     msg_error(Process_Error);
  1090.     return(0);
  1091.      }
  1092.    
  1093.    n = write_region_to_fp(fileno(pp));
  1094.    pclose(pp);
  1095.    return(n);
  1096. }
  1097.  
  1098. #endif
  1099. #endif
  1100.  
  1101. /* called by SLang_load_file
  1102.    Try to open a .slc then a .sl
  1103. */
  1104. #ifdef msdos
  1105. #define VFILE_BUF_SIZE 1024
  1106. #else
  1107. #define VFILE_BUF_SIZE 4096
  1108. #endif
  1109.  
  1110. VFILE *jed_open_lib_file(char *file)
  1111. {
  1112.    char *lib = Jed_Library, libfsl[256], libfslc[256], *libp, buff[256], 
  1113.         *type, *libf;
  1114.    int n, comma = ',';
  1115.    VFILE *vp;
  1116. #ifdef VMS
  1117.    int vmsn;
  1118. #endif
  1119.    
  1120.    if (*file == '.') lib = ""; 
  1121.    else if (*lib == 0)
  1122.      {
  1123.     exit_error("JED_ROOT environment variable needs set.", 0);
  1124.      }
  1125.    
  1126.    n = 0;
  1127.    type = file_type(file);
  1128.    while (1)
  1129.      {
  1130.     libp = SLang_extract_list_element(lib, &n, &comma);
  1131.     n++;
  1132.     strcpy(libfsl, libp);
  1133.     fixup_dir(libfsl);
  1134.     strcat(libfsl, file);
  1135.     strcpy(libfsl, expand_filename(libfsl));
  1136.     if (*type == 0)
  1137.       {
  1138. #ifdef VMS
  1139.          /* remove trailing '.' */
  1140.          if (0 != (vmsn = strlen(libfsl)))
  1141.            { 
  1142.           vmsn--;
  1143.           if (libfsl[vmsn] == '.') libfsl[vmsn] = 0;
  1144.            }
  1145. #endif
  1146.         
  1147.          strcat(libfsl, ".sl");
  1148.          strcpy(libfslc, libfsl);
  1149.          strcat(libfslc, "c");
  1150.          if (file_time_cmp(libfslc, libfsl) > 0) libf = libfslc; else libf = libfsl;
  1151.       }
  1152.     else libf = libfsl;
  1153.     vp = vopen(libf, VFILE_BUF_SIZE, VFILE_TEXT);
  1154.     if ((vp != NULL) || (*libp == 0)) break;
  1155.      }
  1156.    
  1157.    if (Batch != 2)
  1158.      {
  1159.     sprintf(buff, "loading %s", libf);
  1160.     flush_message(buff);
  1161.      }
  1162.    
  1163.    return (vp);
  1164. }
  1165.  
  1166. int jed_close_object(SLang_Load_Type *x)
  1167. {
  1168.    switch (x->type)
  1169.      {
  1170.       case 'F':  /* File */
  1171.     
  1172.     vclose((VFILE *) x->handle);
  1173.     return (1);
  1174.         
  1175.       default: return SL_OBJ_UNKNOWN;
  1176.      }
  1177. }
  1178.  
  1179. char *jed_read_from_file(SLang_Load_Type *x)
  1180. {
  1181.    char *s;
  1182.    unsigned int n;
  1183.    
  1184.    if ((s = vgets((VFILE *) x->handle, &n)) != NULL)
  1185.      {
  1186.     if (s[n - 1] != '\n') s[n] = 0;
  1187.      }
  1188.    
  1189.    return (x->buf = s);
  1190. }
  1191.  
  1192.  
  1193. static char *jed_read_from_buffer(SLang_Load_Type *x)
  1194. {
  1195.    int n;
  1196.    Line *l = (Line *) x->handle;
  1197.    char *buf = x->buf;
  1198.    
  1199.    if (l == NULL) return (NULL);
  1200.    
  1201.    n = l->len;
  1202.    if (n > 255) n = 255;
  1203.    MEMCPY(buf, (char *) l->data, n);
  1204.    buf[n] = 0;
  1205.    x->handle = (LONG) l->next;
  1206.    return(buf);
  1207. }
  1208.  
  1209. /* returns 0 if successful */
  1210. int jed_open_object(SLang_Load_Type *x)
  1211. {
  1212.    
  1213.    switch (x->type)
  1214.      {
  1215.       case 'F':  /* File */
  1216.     
  1217.     x->read = jed_read_from_file;
  1218.  
  1219.     if (0 == (x->handle = (LONG) jed_open_lib_file((char *) x->name)))
  1220.       {
  1221.          return (SL_OBJ_NOPEN);
  1222.       }
  1223.     
  1224.     x->buf = (LONG) NULL;
  1225.     x->n = 0;
  1226.     return (0);
  1227.     
  1228.       case 'B': /* Buffer */
  1229.     x->read = jed_read_from_buffer;
  1230.     x->handle = (LONG) (((Buffer *) (x->name))->beg);
  1231.     return (0);
  1232.     
  1233.       default: return SL_OBJ_UNKNOWN;
  1234.      }
  1235. }
  1236.  
  1237.  
  1238.  
  1239.  
  1240. void load_buffer()
  1241. {   
  1242.    SLang_Load_Type x;
  1243.    Buffer *cbuf = CBuf;
  1244.    int flags = CBuf->flags;
  1245.    char buf[256];
  1246.    Line *l, *lwant;
  1247.    
  1248.    cbuf->flags |= READ_ONLY;
  1249.  
  1250.    x.name = (LONG) cbuf;
  1251.    x.type = 'B';
  1252.    x.buf = buf;
  1253.    
  1254.    SLang_load_object(&x);
  1255.       
  1256.    if (SLang_Error || *Error_Buffer)
  1257.      {
  1258.     SLang_doerror(NULL);
  1259.     pop_to_buffer(cbuf->name);
  1260.     /* if (x.ptr != NULL)
  1261.        { */
  1262.     lwant = (Line *) x.handle;
  1263.     if (lwant != NULL)
  1264.       {
  1265.          bob();
  1266.          while (1)
  1267.            {
  1268.           l = CLine->next;
  1269.           if ((l == NULL) || (l == lwant)) break;
  1270.           CLine = l; LineNum++;
  1271.            }
  1272.       }
  1273.     else eob();
  1274.     Point = x.ofs;
  1275.     /* Point = (int) (x.ptr - buf); */
  1276.     if ((Point >= 0) && (Point < CLine->len))
  1277.       {
  1278.          (void) skip_whitespace();
  1279.       }
  1280.     else Point = 0;
  1281.      /* } */
  1282.      }
  1283.    cbuf->flags = flags;
  1284. }
  1285.  
  1286.  
  1287. void get_key_function()
  1288. {
  1289.    char *s;
  1290.    int kind;
  1291.    
  1292.    s = find_key(&kind);
  1293.    if (s != NULL)
  1294.      {
  1295.     if (SLKeyBoard_Quit && (SLang_Error == USER_BREAK))
  1296.       {
  1297.          SLang_Error = 0;
  1298.          SLKeyBoard_Quit = 0;
  1299.          /* s = "kbd_quit"; */
  1300.       }
  1301.     SLang_push_integer(kind);
  1302.      }
  1303.    else s = "";
  1304.    SLang_push_string(s);
  1305. }
  1306.  
  1307. int mini_complete()
  1308. {
  1309.    char *pl, *pb;
  1310.    char last[256], buf[256], *tmp;
  1311.    static char prev[256];
  1312.    int n;
  1313.    static int flag = 0;  /* when flag goes 0, we call open */
  1314.  
  1315.    if (complete_open == NULL) return ins_char_cmd();
  1316.  
  1317.    Point = 0;
  1318.    push_mark();
  1319.    eob();
  1320.    if (NULL == (tmp = make_buffer_substring(&n))) return(1);
  1321.    
  1322.    strncpy(buf, tmp, 255);
  1323.    buf[255] = 0;
  1324.    SLFREE(tmp);
  1325.  
  1326.    if ((SLang_Last_Key_Char == ' ') && ((long) Last_Key_Function == (long) mini_complete))
  1327.      {
  1328.     if (!flag || !(flag = (*complete_next)(buf)))
  1329.       {
  1330.          strcpy(buf, prev);
  1331.          flag = (*complete_open)(buf);
  1332.       }
  1333.     strcpy(last, buf);
  1334.     n = -1;
  1335.      }
  1336.    else
  1337.      {
  1338.     n = 0;
  1339.     strcpy(prev, buf);  /* save this search context */
  1340.      }
  1341.  
  1342.    if (!n) flag = (*complete_open)(buf);
  1343.    if (!n && flag)
  1344.      {
  1345.     strcpy(last, buf);
  1346.  
  1347.     /* This do loop tests all values from complete_next and returns the
  1348.        smallest length match of initial characters of buf */
  1349.     do
  1350.       {
  1351.          if ((n == 0) && (SLang_Last_Key_Char == '\t'))
  1352.            {
  1353.           set_buffer (Completion_Buffer);
  1354.           erase_buffer ();
  1355.           CBuf->flags |= BURIED_BUFFER;
  1356.           insert_string ("!!! Use Page Up/Down keys to scroll this window. !!!\n");
  1357.            }
  1358.          
  1359.          n++;
  1360.          pl = last;
  1361.          pb = buf;
  1362. #ifdef __os2__
  1363.           if (complete_open == open_bufflist)
  1364.            while (*pl && (tolower(*pl) == tolower(*pb))) pl++, pb++;
  1365.           else  /* next statement */
  1366. #endif
  1367.          while (*pl && (*pl == *pb)) pl++, pb++;
  1368.          *pl = 0;
  1369.          
  1370.          if (SLang_Last_Key_Char == '\t')
  1371.            {
  1372.           while (*pb) pb++;
  1373.           quick_insert ((unsigned char *)buf, (int) (pb - buf));
  1374.           newline ();
  1375.            }
  1376.       }
  1377.     
  1378.     while(0 != (flag = (*complete_next)(buf)));
  1379.     
  1380. #ifdef __os2__
  1381.     /* OS/2 uses case-insensitive search on buffer-names. Set the 
  1382.      * flag if there is an exact match, so that completion will
  1383.      * cycle without repeats through all the matches. */
  1384.     
  1385.     if (complete_open == open_bufflist) {
  1386.        strcpy(buf, last);
  1387.        (*complete_open)(buf);
  1388.        do {
  1389.           if (!strcmp(buf, last)) {
  1390.          flag = 1; break;
  1391.           }
  1392.        } while ((*complete_next)(buf));
  1393.      }
  1394. #endif
  1395.      }
  1396.  
  1397.    if ((n > 1) && (SLang_Last_Key_Char == '\t') && (Last_Completion_Buffer == NULL))
  1398.      {
  1399.     Last_Completion_Windows = num_windows () - 1;   /* not including mini */
  1400.     Last_Completion_Buffer = pop_to_buffer (Completion_Buffer);
  1401.     bob ();
  1402.      }
  1403.    
  1404.    while ((CBuf != MiniBuffer) || !IS_MINIBUFFER) other_window ();
  1405.    
  1406.    if (n)
  1407.      {
  1408.     erase_buffer();
  1409.     /* strcpy(last, buf); */
  1410.     insert_string(last);
  1411.     if ((n == 1) && ((long) Last_Key_Function == (long) mini_complete))
  1412.       message("[Sole Completion.]");
  1413.      }
  1414.    else msg_error("No Match!");
  1415.  
  1416.    return(1);
  1417. }
  1418.  
  1419. int what_char()
  1420. {
  1421.    if (eobp()) return(0);
  1422.    return( (int) *(CLine->data + Point) );
  1423. }
  1424.  
  1425. void update_cmd(int *force)
  1426. {
  1427.    if (Batch) return;
  1428.    JWindow->trashed = 1;
  1429.    update((Line *) NULL, *force, 0);
  1430. }
  1431.  
  1432. void call_cmd(char *str)
  1433. {
  1434.    int (*fp)(void);
  1435.  
  1436.    if (NULL == (fp = (int (*)(void)) SLang_find_key_function(str, CBuf->keymap)))
  1437.      {
  1438.     msg_error("Function does not exist!");
  1439.      }
  1440.    else (void) (*fp)();
  1441. }
  1442.  
  1443. void copy_region_cmd(char *name)
  1444. {
  1445.    Buffer *buf;
  1446.  
  1447.    if (NULL != (buf = find_buffer(name)))
  1448.      {
  1449.     copy_region_to_buffer(buf);
  1450.      }
  1451.    else msg_error("Unable to find buffer.");
  1452. }
  1453.  
  1454. #ifndef pc_system
  1455.  
  1456. void screen_w80()
  1457. {
  1458.    tt_narrow_width();
  1459.    change_screen_size(80, *tt_Screen_Rows);
  1460. }
  1461.  
  1462. void screen_w132()
  1463. {
  1464.    tt_wide_width();
  1465.    change_screen_size(132, *tt_Screen_Rows);
  1466. }
  1467. #endif
  1468.  
  1469. char *make_line_string(char *string)
  1470. {
  1471.    unsigned char *tmp, *p1, *p2;
  1472.    int n;
  1473.  
  1474.    if (CBuf->marks == NULL)
  1475.      {
  1476.     p1 = CLine->data + Point;
  1477.     p2 = CLine->data + CLine->len;
  1478.      }
  1479.    else
  1480.      {
  1481.     p1 = CLine->data + CBuf->marks->point;
  1482.     p2 = CLine->data + Point;
  1483.     if (p2 < p1)
  1484.       {
  1485.          tmp = p1; p1 = p2; p2 = tmp;
  1486.       }
  1487.     pop_mark(&Number_Zero);
  1488.      }
  1489.    n = (int) (p2 - p1);
  1490.    if (n > 254) n = 254;
  1491.    MEMCPY(string, (char *) p1, n);
  1492.    string[n] = 0;
  1493.    return(string);
  1494. }
  1495.  
  1496.  
  1497. char *make_buffer_substring(int *np)
  1498. {
  1499.    Line *tthis, *beg;
  1500.    int n = 1, dn, thisp;
  1501.    unsigned char *buf;
  1502.  
  1503.    if (!check_region(&n)) return (NULL);      /* spot pushed */
  1504.    /* Point now at end of the region */
  1505.    
  1506.    beg = tthis = CBuf->marks->line;
  1507.    thisp = CBuf->marks->point;
  1508.    n = 0;
  1509.    pop_mark(&n);
  1510.    
  1511.    while (tthis != CLine)
  1512.      {
  1513.     n += tthis->len;
  1514.     tthis = tthis->next;
  1515.      }
  1516.    n -= thisp;
  1517.    n += Point;
  1518.    
  1519.    if (NULL == (buf = (unsigned char *) SLMALLOC(n + 1)))
  1520.      {
  1521.     msg_error("Malloc Error");
  1522.     pop_spot();
  1523.     return (NULL);
  1524.      }
  1525.    
  1526.    if (CLine == (tthis = beg))
  1527.      {
  1528.     MEMCPY((char *)buf, (char *) (tthis->data + thisp), n);
  1529.      }
  1530.    else
  1531.      {
  1532.     n = 0;
  1533.     while (tthis != CLine)
  1534.       {
  1535.          dn = tthis->len - thisp;
  1536.          MEMCPY((char *)(buf + n), (char *) (tthis->data + thisp), dn);
  1537.          tthis = tthis->next;
  1538.          thisp = 0;
  1539.          n += dn;
  1540.       }
  1541.     MEMCPY((char *)(buf + n), (char *) tthis->data, Point);
  1542.     n += Point;
  1543.      }
  1544.    buf[n] = 0;
  1545.    *np = n;
  1546.    pop_spot();
  1547.    return ((char *) buf);
  1548. }
  1549.  
  1550. void buffer_substring()
  1551. {
  1552.    char *buf;
  1553.    int n;
  1554.    if (NULL == (buf = make_buffer_substring(&n))) return;
  1555.    SLang_push_malloced_string((char *)buf);
  1556. }
  1557.  
  1558.  
  1559. int markp(void)
  1560. {
  1561.    return (CBuf->marks != NULL);
  1562. }
  1563.  
  1564. int dup_mark(void)
  1565. {
  1566.    if (CBuf->marks == NULL) return(0);
  1567.  
  1568.    push_spot();
  1569.    goto_mark(CBuf->marks);
  1570.    push_mark();
  1571.    pop_spot();
  1572.    return(1);
  1573. }
  1574.  
  1575. void mini_read(char *prompt, char *def, char *stuff)
  1576. {
  1577.    char *buf;
  1578.    int n;
  1579.  
  1580.    complete_open = NULL;
  1581.    if (NULL == (buf = read_from_minibuffer(prompt, def, stuff, &n)))
  1582.      SLang_push_string ("");
  1583.    else SLang_push_malloced_string(buf);
  1584. }
  1585.  
  1586.  
  1587. void get_buffer_info(void)
  1588. {
  1589.    SLang_push_string(CBuf->file);
  1590.    SLang_push_string(CBuf->dir);
  1591.    SLang_push_string(CBuf->name);
  1592.    SLang_push_integer(CBuf->flags);
  1593. }
  1594.  
  1595. void set_buffer_info(char *file, char *dir, char *name, int *flags)
  1596. {
  1597.    strcpy(CBuf->file, file);
  1598.    strcpy(CBuf->dir, dir);
  1599.    strcpy(CBuf->name, name);
  1600.    CBuf->flags = *flags;
  1601. }
  1602.  
  1603. void make_buffer_list(void)
  1604. {
  1605.    int n = 0;
  1606.    Buffer *b;
  1607.  
  1608.    b = CBuf;
  1609.  
  1610.    do
  1611.      {
  1612.     SLang_push_string(b->name);
  1613.     b = b->next;
  1614.     n++;
  1615.      }
  1616.    while (b != CBuf);
  1617.    SLang_push_integer(n);
  1618. }
  1619.  
  1620. int window_size_intrinsic(int *what)
  1621. {
  1622.    register int n = 0;
  1623.    switch (*what)
  1624.      {
  1625.       case 'r': n = JWindow->rows; break;
  1626.       case 'c': n = JWindow->column; break;
  1627.       case 't': n = JWindow->top; break;
  1628.       case 'w': n = JWindow->width; break;
  1629.       default: SLang_Error = UNKNOWN_ERROR;
  1630.      }
  1631.    return (n);
  1632. }
  1633.  
  1634. int what_mode(void)
  1635. {
  1636.    SLang_push_string (CBuf->mode_str);
  1637.    return CBuf->modes;
  1638. }
  1639.  
  1640. /* Given a file name with wildcards return expanded list to S-Lang stack
  1641.  *  with number.  This does NOT work on unix with wild cards.  Instead the 
  1642.  *  expansion is file* (completion) */
  1643. int expand_wildcards(char *file)
  1644. {
  1645.    char buf[256];
  1646.    int n = 0;
  1647.    
  1648.    strcpy(buf, file);
  1649.           
  1650.    if (sys_findfirst(buf))
  1651.      {
  1652.     do
  1653.       {
  1654.          n++;
  1655.          SLang_push_string(buf);
  1656.       }
  1657.     while (sys_findnext(buf));
  1658.      }
  1659.    return (n);
  1660. }
  1661.  
  1662. void jed_traceback(char *s)
  1663. {
  1664.    char *n;
  1665.    if (!Batch)
  1666.      {
  1667.     n = CBuf->name;
  1668.     set_buffer("*traceback*");
  1669.     eob();
  1670.     insert_string(s);
  1671.     set_buffer(n);
  1672.      }
  1673.    else fprintf(stderr, s);
  1674. }
  1675.  
  1676. #if 0
  1677. static struct 
  1678. {
  1679.    int depth = 0;
  1680.    char *name[20];
  1681.    int marks[20];
  1682. } FName_Stack;
  1683.  
  1684. void enter_function(char *name)
  1685. {
  1686.    if (depth > 20) 
  1687.      {
  1688.     msg_error("Function Stack too deep.");
  1689.     return;
  1690.      }
  1691.    FName_Stack->name[depth] = name;
  1692.    FName_Stack->marks[depth] = 0;
  1693. }
  1694.  
  1695. void exit_function(char *name)
  1696. {
  1697.    int n = FName_Stack->marks[depth];
  1698.    
  1699. }
  1700. #endif
  1701.  
  1702.  
  1703. #if 0
  1704. void make_istring(char *buf, int i)
  1705. {
  1706.    register char *b, *b1, ch;
  1707.    int sign, d;
  1708.    
  1709.    b = buf;
  1710.    if (i >= 0)
  1711.      {
  1712.     sign = 1;
  1713.      }
  1714.    else 
  1715.      {
  1716.     sign = -1;
  1717.     i = -i;
  1718.      }
  1719.    do
  1720.      {
  1721.     d = i % 10;
  1722.     i = i / 10;
  1723.     *b++ = d + '0';
  1724.      }
  1725.    while (i > 0);
  1726.  
  1727.    if (sign == -1) *b++ = '-';
  1728.    *b-- = 0;
  1729.    b1 = buf;
  1730.    /* now reverse it */
  1731.    while (b > b1)
  1732.      {
  1733.     ch = *b;
  1734.     *b-- = *b1;
  1735.     *b1++ = ch;
  1736.      }
  1737. }
  1738.  
  1739. #include <stdarg.h>
  1740.  
  1741. char *simple_sprintf(char *str, char *fmt, ...)
  1742. {
  1743.    va_list ap;
  1744.    register char ch, *s = str, *string;
  1745.    char *fmtmax = fmt + strlen(fmt);
  1746.    int dig;
  1747.    char buf[80];
  1748.    
  1749.    va_start(ap, fmt);
  1750.    
  1751.    
  1752.    while (fmt < fmtmax)
  1753.      {
  1754.     ch = *fmt++;
  1755.     switch(ch)
  1756.       {
  1757.        case '%': ch = *fmt++;
  1758.          string = buf;
  1759.          switch(ch)
  1760.            {
  1761.         case 'c': ch = (char) va_arg(ap, int);  /* drop */
  1762.         case '%': buf[0] = ch; buf[1] = 0; break;
  1763.         case 's': 
  1764.           string = va_arg(ap, char *); break;
  1765.         case 'l': 
  1766.         case 'd':
  1767.         default: 
  1768.           dig = va_arg(ap, int);
  1769.           make_istring(buf, dig);
  1770.           break;
  1771.            }
  1772.          while (*string) *s++ = *string++;
  1773.          break;
  1774.        case '\\': 
  1775.          ch = *fmt++;
  1776.          switch(ch)
  1777.            {
  1778.         case 'b': ch = '\b'; break;
  1779.         case 'r': ch = 13; break;
  1780.         case 'n': ch = '\n'; break;
  1781.         case 'e': ch = 27; break;
  1782.         case 'a': ch = 7; break;
  1783.            }
  1784.          /* drop */
  1785.        default: 
  1786.          *s++ = ch;
  1787.       }
  1788.      }
  1789.    va_end(ap);
  1790.    *s = 0;
  1791.    return(str);
  1792. }
  1793. #endif
  1794.  
  1795.  
  1796. char *command_line_argv(int *nn)
  1797. {
  1798.    int n = *nn;
  1799.    if ((n >= Main_Argc) || (n < 0)) 
  1800.      {
  1801.     msg_error("Argc out of bounds.");
  1802.     n = 0;
  1803.      }
  1804.    
  1805.    return Main_Argv[n];
  1806. }
  1807.  
  1808. void count_chars(void)
  1809. {
  1810.    unsigned long n = 0, m = 0;
  1811.    int ch;
  1812.    char buf[132];
  1813.    Line *l = CBuf->beg;
  1814.    
  1815.    while (l != NULL)
  1816.      {
  1817.     n += l->len;
  1818.     l = l->next;
  1819.      }
  1820.    l = CBuf->beg;
  1821.    while (l != CLine)
  1822.      {
  1823.     m += l->len;
  1824.     l = l->next;
  1825.      }
  1826.    m += Point + 1;
  1827.    ch = eobp() ? 0 : (int) *(CLine->data + Point);
  1828.    sprintf(buf, "'@'=%d/0x%x, point %lu of %lu", ch, ch, m, n);
  1829.    if (ch != 0) buf[1] = ch;
  1830.    else buf[0] = '^';
  1831.    SLang_push_string(buf);
  1832. }
  1833.  
  1834. static void jed_clear_error(void)
  1835. {
  1836.    *Error_Buffer = 0;
  1837.    SLKeyBoard_Quit = 0;
  1838. }
  1839.  
  1840.  
  1841. int (*X_Init_SLang_Hook)(void);
  1842.  
  1843. void init_minibuffer()
  1844. {
  1845.    Buffer *tmp;
  1846.  
  1847.    tmp = CBuf;
  1848.  
  1849.    The_MiniBuffer = make_buffer();
  1850.    The_MiniBuffer->modes = 0;
  1851.    strcpy(The_MiniBuffer->name, " <mini>");
  1852.    /* do some initializing */
  1853.    switch_to_buffer(The_MiniBuffer); 
  1854.    remake_line(132);
  1855.    The_MiniWindow = create_window(*tt_Screen_Rows, 1, 1, *tt_Screen_Cols);
  1856.    The_MiniWindow->buffer = CBuf;
  1857.    Buffer_Local.tab = 0;
  1858.    switch_to_buffer(tmp);
  1859.    SLang_Dump_Routine = jed_traceback;
  1860.  
  1861. #ifdef __GO32__
  1862.    SLang_Interrupt = i386_check_kbd;
  1863. #endif
  1864.    
  1865. #if 0
  1866.    SLang_Enter_Function = enter_function;
  1867.    SLang_Exit_Function = exit_function;
  1868. #endif
  1869.    if (!init_SLang()
  1870. #ifdef FLOAT_TYPE
  1871.        || !init_SLmath()
  1872. #endif
  1873. #ifndef pc_system
  1874. #ifdef unix
  1875.        || !init_SLunix()
  1876. #endif
  1877. #endif
  1878.        || !init_jed_intrinsics()
  1879.        || !register_jed_classes ()
  1880.        || ((X_Init_SLang_Hook != NULL) && !(*X_Init_SLang_Hook)()))
  1881.      {
  1882.     exit_error("Unable to initialize S-Lang!", 0);
  1883.      }
  1884.  
  1885.    /* use jed rouotines instead of default slang ones */
  1886.    SLang_Error_Routine = msg_error;
  1887.    SLang_User_Open_Slang_Object = jed_open_object;
  1888.    SLang_User_Close_Slang_Object = jed_close_object;
  1889.    SLang_User_Clear_Error = jed_clear_error;
  1890. }
  1891.