/*-----------------------------------------------------------------
|                           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 >>>>                                      |
|                                                                 |
| ABBREV2                                                         |
|   This version uses the ARRAY capabilities which are found      |
| starting with version 1.3 of ME/NYEDIT.                         |
|                                                                 |
-----------------------------------------------------------------*/

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

#define MAXABBREVS  20          /* Change this for more abbrevs */

int    NumAbbrevs;              /* Current # of abbrevs defined */
string Abbrevs[MAXABBREVS];     /* array of abbrevs - "abbrev expansion" */
string AbbrevFilename;          /* Name of the abbrev array */

init()
{
  assign_key("load_abbrev",   ALT_A);   /* ALT A creates/loads an abbrev */
  assign_key("expand_abbrev", ALT_E);   /* ALT E expands an abbrev    */
  assign_key("insert_abbrev", ALT_I);   /* ALT I inserts a new 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;

  /* back up and extract the abbrev from the text */
  origcol = currcol();
  prevword();
  startcol = currcol();
  
  abbrev = substr(currline(), startcol, origcol - startcol);
  i      = search_abbrev(abbrev);
  
  if (i)                /* it was found */
  {
    delword();          /* get rid of the abbrev */
    insert(substr(Abbrevs[i], index(Abbrevs[i], " ")+1, 100));
  }
  else                  /* abbrev not found */
  {
    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;
{
  for (i = 1;  i <= NumAbbrevs;  i++)
    if (substr(Abbrevs[i], 1, index(Abbrevs[i]," ") - 1) == candidate)
      return i;
  return 0;
}

/* 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 */
  if ((i = search_abbrev(abbrev)) > 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;
  
  if (i == 0)
  {
    NumAbbrevs++;
    i = NumAbbrevs;
  }
  Abbrevs[i] = sprintf("%s %s", abbrev, defn);
}

/* delete_abbrev - deletes an abbrev from the abbrev buffer */
delete_abbrev()
{
  string abbrev;
  
  if ((abbrev = get_tty_str("Abbrev to delete : ")) == "")
    return;
  if ((i = search_abbrev(abbrev)) == 0)   /* Abbrev not found */
  {
    bell();
    get_tty_str("The abbrev wasn't found");
  }
  else                          /* The abbrev was found */
  {
    while (i < NumAbbrevs)
      Abbrevs[i] = Abbrevs[i+1];
    NumAbbrevs--;
    get_tty_str("The abbrev was deleted");
  }
}

/************************* 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           */
  AbbrevFilename = fname;
  NumAbbrevs = 0;

  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
  {
    for (NumAbbrevs = 1;  currlinenum() < lastlinenum();  NumAbbrevs++)
    {
      Abbrevs[NumAbbrevs] = currline();
      down();
    }
    Abbrevs[NumAbbrevs] = currline();
    get_tty_str("Abbrev file loaded");
  }

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


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

  if (NumAbbrevs <= 0)
  {
    get_tty_str("There are no abbrevs defined");
    return;
  }

  oldbuf = currbuf();

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

  setcurrbuf(abuf = create_buffer(fname));      /* create/load the buffer */
  if (currline() != "")                         /* a new buffer? */
  {
    message("Overwrite the existing abbrev file? (y/N)");
    if ((c = get_tty_char()) != 'y' && c != 'Y')
      return;
  }

  for (i = 1;  i <= NumAbbrevs;  i++)
  {
    insert(Abbrevs[i]);
    insert("\n");
  }

  writefile(fname);

  delete_buffer(abuf);          /* remove the temp buffer */
  setcurrbuf(oldbuf);           /* return to our current buffer */
}
