/*-----------------------------------------------------------------
|                           ABBREV                                |
| This macro sorta simulates the abbrev facility that was made    |
| popular in EMACS, and was later commercialized even further in  |
| packages like Productivity Plus (TM). It also can be considered |
| to be a way to further enhance the editor's keyboard macro      |
| facility.                                                       |
|                                                                 |
| The main idea is that we have a buffer where each line contains |
| an abbreviation, a space, and the abbrev's expansion. When we   |
| are editing text, we can type an abbrev, hit a function key, and|
| have the abbrev expanded automatically. (Note - instead of a    |
| function key, you might optionally program this macro to be     |
| invoked when you hit the space bar.)                            |
|                                                                 |
| For instance, if you wanted the word "ii" to be an abbrev for   |
| the phrase "Institute of Intermediate Ignoramuses", you could   |
| enter this abbrev and expansion in the abbrev buffer. When      |
| you typed "ii" and then the EXPAND ABBREV function key, "ii"    |
| would be replaced by "Institute of ...".                        |
|                                                                 |
| This package allows you to create/load and write an abbrev      |
| buffer. You may add new abbrevs and delete existing abbrevs.    |
| Of course, you may want to add other functions which can operate|
| of abbrevs. For this, you need the macro compiler.              |
| The first extension which comes to mind is support for multiple |
| abbrev buffers.                                                 |
|                                                                 |
| ENJOY!!!!                                                       |
|                                                                 |
| <<<< Marc Adler  7/87 >>>>                                      |
-----------------------------------------------------------------*/

#define ALT_A  158
#define ALT_E  146
#define ALT_I  151

int  CurrAbbrevBuf;
int  CurrAbbrevLine;

init()
{
  assign_key("load_abbrev",   ALT_A);   /* ALT A creates/loads an abbrev */
  assign_key("expand_abbrev", ' ');     /* space expands an abbrev    */
  assign_key("insert_abbrev", ALT_I);   /* ALT I inserts a new abbrev */
  load_abbrev();
}


/* expand_abbrev - expands an abbrev when you press ALT E. We assume that */
/*                 the cursor is just to the right of the abbrev to expand*/
expand_abbrev()
{
  string abbrev,
         defn;

  insert(" ");    
  /* back up and extract the abbrev from the text */
  origcol = currcol();
  origrow = currlinenum();
  prevword();         
  if (origrow != currlinenum())  {
        goline(origrow);
        setcol(origcol);
        return;
  }
  startcol = currcol();
  
  abbrev = substr(currline(), startcol, origcol - startcol - 1);
  defn   = search_abbrev(abbrev);
  
  if (defn != "")       /* it was found */
  {
    delword();          /* get rid of the abbrev */
    insert(defn);       /* and replace it with the expansion */
  }
  else                  /* abbrev not found */
  {
    goline(origrow);
    setcol(origcol);    /* restore the cursor */
/*    bell();   */
  }
}

/* search_abbrev - searches the current abbrev buffer for the requested */
/*                 abbrev. Return the NULL string if not found.         */
search_abbrev(candidate)
  string candidate;
{
  /* Go to the start of the abbrev buffer */
  oldbuf = currbuf();
  setcurrbuf(CurrAbbrevBuf);
  gobof();

  if (fsearch(pattern = sprintf("^%s ", candidate)) > 0)    /* found */
  {
    CurrAbbrevLine = currlinenum();
    defn = substr(currline(), strlen(pattern), 128);
    setcurrbuf(oldbuf);
    return defn;
  }
  else          /* not found */
  {
    CurrAbbrevLine = 0;
    setcurrbuf(oldbuf);
    return "";
  }
}


/* insert_abbrev - inserts an abbrev and the expansion in the current */
/*                 abbrev buffer.                                     */
insert_abbrev()
{
  string abbrev, defn;
  
  if ((abbrev = get_tty_str("Abbrev to insert : ")) == "")
    return;

  /* Search the abbrev buffer for a duplicate entry */
  search_abbrev(abbrev);
  if (CurrAbbrevLine != 0)
  {
     c = get_tty_str("Abbrev already exists - replace it? (Y/N)");
     if (c != "y" && c != "Y")
       return;
  }

  /* Prompt the user for the expansion */
  if ((defn = get_tty_str("Expansion : ")) == "")
    return;
  
  oldbuf = currbuf();
  setcurrbuf(CurrAbbrevBuf);

  if (CurrAbbrevLine == 0)      /* inserting a new abbrev at the eof */
  {
    goeof();
    if (currline() != "")
      insert("\n");
    insert(sprintf("%s %s", abbrev, defn));
  }
  else                          /* replacing an existing entry */
  {
    goline(CurrAbbrevLine);
    deleol();
    insert(sprintf("%s %s", abbrev, defn));
  }

  setcurrbuf(oldbuf);
}

/* delete_abbrev - deletes an abbrev from the abbrev buffer */
delete_abbrev()
{
  string abbrev;
  
  if ((abbrev = get_tty_str("Abbrev to delete : ")) == "")
    return;
  search_abbrev(abbrev);
  if (CurrAbbrevLine == 0)      /* Abbrev not found */
  {
    bell();
    get_tty_str("The abbrev wasn't found");
  }
  else                          /* The abbrev was found */
  {
    oldbuf = currbuf();         /* save the curr buffer id */
    setcurrbuf(CurrAbbrevBuf);  /* go to the abbrev buffer */
    goline(CurrAbbrevLine);     /* and the delete the line */
    delline();
    setcurrbuf(oldbuf);
  }
}

/************************* I/O OPERATIONS ***********************/

/* load_abbrev - creates a new abbrev buffer, or loads in an existing one.*/
/* Abbrev files will have the default extension of ABV. */
load_abbrev()
{
  string fname;
  
  if ((fname = get_tty_str("Abbrev file : ")) == "")    /* prompt the user */
    return;
  if (!index(fname, "."))            /* User didn't supply an extension */
    fname = strcat(fname, ".ABV");   /* Add the ABV extension           */

  oldbuf = currbuf();                /* save the current buffer id      */

  setcurrbuf(abuf = create_buffer(fname));      /* create/load the buffer */
  if (currline() == "")                         /* a new buffer? */
    get_tty_str("New abbrev buffer");
  else
    get_tty_str("Abbrev file loaded");
  CurrAbbrevBuf = abuf;

  setcurrbuf(oldbuf);                 /* Restore the original editing buffer */
}


/* write_abbrev - writes the current abbrev buffer to a file */
write_abbrev()
{
  string fname;

  oldbuf = currbuf();

  /* Get the current abbrev buffer's name, maybe concat */
  /* the ABV extension and dump it to a file.           */
  setcurrbuf(CurrAbbrevBuf);
  fname = filename();
  if (!index(fname, "."))
    fname = strcat(fname, ".ABV");
  writefile(fname);

  setcurrbuf(oldbuf);
}
