home *** CD-ROM | disk | FTP | other *** search
- #ifndef NO_IDENT
- static char *Id = "$Id: cmdstk.c,v 1.8 1995/10/21 17:49:10 tom Exp $";
- #endif
-
- /*
- * Title: cmdstk.c
- * Author: Thomas E. Dickey
- * Created: 17 Oct 1984 (broke out of 'dircmd')
- * Last update:
- * 27 May 1995, split-out cmdstk.h
- * 18 Feb 1995, port to AXP (renamed 'alarm')
- * 14 May 1985, was testing wrong variable in entry to '_put'.
- * 30 Apr 1985, always store commands in lower-case.
- * 27 Apr 1985, don't concat ' ' on end of stored-string!!
- * 22 Dec 1984, permit bidirectional movement in 'cmdstk_get'.
- * 18 Dec 1984, restrict stack to a page of memory. Re-coded
- * from a linked-list to a ring buffer.
- *
- * Function: This module maintains a buffer of the most-recently-used
- * command strings of FLIST, permitting the user to retrieve
- * commands for re-use or alteration.
- */
-
- #include <stdlib.h>
- #include <string.h>
-
- #include "bool.h"
- #include "crt.h"
- #include "cmdstk.h"
- #include "strutils.h"
-
- /*
- * Local (static) data:
- *
- * Save FLIST "visible commands" in a stack-list in memory, to provide
- * last-command retrieval.
- */
-
- static CMDSTK *cmdstk_ = 0;
-
- #define HEAD cmdstk_->head
- #define STORED cmdstk_->stored
- #define DEPTH cmdstk_->depth
- #define TEXT(j) cmdstk_->text[j]
-
- #define INDEX(j) cmdstk_index(HEAD-(j))
-
- static int cmdstk_index (int n);
-
- /*
- * Allocate a page-buffer for the command-stack. We provide a hierarchy
- * for FLIST by copying the stack from a higher level to this level. Thus,
- * there is no loss of continuity on entering a new level; but on exit we
- * resume with the set of stacked commands which were present on nesting.
- */
- CMDSTK *
- cmdstk_init (void)
- {
- CMDSTK *new_ = calloc (1, PAGESIZE),
- *old_ = cmdstk_;
-
- if (cmdstk_) *new_ = *cmdstk_;
- cmdstk_ = new_;
- return (old_);
- }
-
- void
- cmdstk_free (CMDSTK *old_)
- {
- if (cmdstk_) cfree (cmdstk_);
- cmdstk_ = old_;
- }
-
- void
- cmdstk_tos (void)
- {
- DEPTH = -1; /* Provide index to most-recent */
- }
-
- /*
- * Retrieve the (next) most recent item on the command stack. If we are at
- * the end, sound an alarm. Return TRUE iff there is text to process.
- * Note that if no commands have been entered, we do not alter the output
- * string from whatever the caller set it to.
- */
- int
- cmdstk_get (char *string, int dir)
- {
- int deep = DEPTH + dir;
-
- if ((deep < STORED) && (deep >= 0))
- {
- strcpy (string, TEXT(INDEX(deep)));
- DEPTH = deep;
- return (TRUE);
- }
- sound_alarm ();
- return (*string);
- }
-
- /*
- * If the current command is the same as one of the last 'RING' commands,
- * do not save it. This permits the user to toggle between a couple
- * of commands in the retrieval state.
- *
- * A command which duplicates one in the last 'RING' levels causes this
- * item to be "popped" to the top-level of the ring. The entire stack
- * is pushed only when no match is found in the ring.
- */
- void
- cmdstk_put (char *s_)
- {
- register
- int j, k;
- char string[CRT_COLS+1];
- #define RING 3
-
- if (*s_) /* Save all "visible" commands */
- {
- strlcpy (string, s_);
- if (STORED)
- {
- for (j = 0; j < RING; j++)
- {
- if (!strcmp (string, TEXT(INDEX(j))))
- {
- for (k = j; k > 0; k--)
- strcpy (TEXT(INDEX(k)),
- TEXT(INDEX(k-1)));
- strcpy (TEXT(HEAD), string);
- return;
- }
- }
- }
- HEAD = INDEX(-1);
- if (STORED < MAXSTK) STORED += 1;
- strcpy (TEXT(HEAD), string);
- }
- }
-
- /*
- * This procedure is called by a "visible" command to alter to extend its
- * saved-text, for command retrieval. In particular, it is called by the
- * protection-editor.
- */
- void
- cmdstk_chg (char *string)
- {
- if (STORED > 0) /* Only "change" if there is something */
- {
- HEAD = INDEX(1); /* Redo this entry */
- cmdstk_tos ();
- STORED--;
- cmdstk_put (string);
- }
- else
- sound_alarm ();
- }
-
- /*
- * Compute an index in the queue, accounting for wraparound.
- */
- static int
- cmdstk_index (int n)
- {
- if (n < 0) n = MAXSTK - n;
- else if (n >= MAXSTK) n = n - MAXSTK;
- return (n);
- }
-