Back to index

tetex-bin  3.0
Defines | Functions | Variables
infomap.c File Reference
#include "info.h"
#include "infomap.h"
#include "funs.h"
#include "terminal.h"
#include "infokey.h"
#include "variables.h"

Go to the source code of this file.

Defines

#define NUL   '\0'
#define To_dst(c)

Functions

static int keymap_bind_keyseq (Keymap map, const char *keyseq, KEYMAP_ENTRY *keyentry)
Keymap keymap_make_keymap (void)
static FUNCTION_KEYSEQfind_function_keyseq (Keymap map, int c, Keymap rootmap)
static void add_function_keyseq (InfoCommand *function, const char *keyseq, Keymap rootmap)
static void remove_function_keyseq (InfoCommand *function, const char *keyseq, Keymap rootmap)
Keymap keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot)
void keymap_discard_keymap (Keymap map, Keymap rootmap)
static unsigned long filesize (int f)
static int getint (unsigned char **sp)
static int fetch_user_maps (void)
static int decode_keys (unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int dlen)
static int section_to_keymaps (Keymap map, unsigned char *table, unsigned int len)
static void section_to_vars (unsigned char *table, unsigned int len)
void initialize_info_keymaps (void)

Variables

Keymap info_keymap = NULL
Keymap echo_area_keymap = NULL
static unsigned char default_emacs_like_info_keys []
static unsigned char default_emacs_like_ea_keys []
static unsigned char default_vi_like_info_keys []
static unsigned char default_vi_like_ea_keys []
static unsigned char * user_info_keys
static unsigned int user_info_keys_len
static unsigned char * user_ea_keys
static unsigned int user_ea_keys_len
static unsigned char * user_vars
static unsigned int user_vars_len

Define Documentation

#define NUL   '\0'

Definition at line 847 of file infomap.c.

#define To_dst (   c)
Value:
do { \
  if ((unsigned int) (d - dst) < dlen) *d++ = (c); \
} while (0)

Function Documentation

static void add_function_keyseq ( InfoCommand function,
const char *  keyseq,
Keymap  rootmap 
) [static]

Definition at line 93 of file infomap.c.

{
  FUNCTION_KEYSEQ *ks;

  if (function == NULL ||
      function == InfoCmd(info_do_lowercase_version) ||
      function == InfoCmd(ea_insert))
    return;
  ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ));
  ks->next = function->keys;
  ks->map = rootmap;
  ks->keyseq = xstrdup(keyseq);
  function->keys = ks;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int decode_keys ( unsigned char *  src,
unsigned int  slen,
unsigned char *  dst,
unsigned int  dlen 
) [static]

Definition at line 1597 of file infomap.c.

{
       unsigned char *s = src;
       unsigned char *d = dst;

#define To_dst(c) do { \
  if ((unsigned int) (d - dst) < dlen) *d++ = (c); \
} while (0)

       while ((unsigned int) (s - src) < slen)
       {
              unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s;

              if (c == SK_ESCAPE)
              {
                     char *t;
                     static char lit[] = { SK_ESCAPE, NUL };

                     switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0')
                     {
                     case SK_RIGHT_ARROW: t = term_kr; break;
                     case SK_LEFT_ARROW:  t = term_kl; break;
                     case SK_UP_ARROW:    t = term_ku; break;
                     case SK_DOWN_ARROW:  t = term_kd; break;
                     case SK_PAGE_UP:     t = term_kP; break;
                     case SK_PAGE_DOWN:   t = term_kN; break;
                     case SK_HOME:        t = term_kh; break;
                     case SK_END:         t = term_ke; break;
                     case SK_DELETE:             t = term_kx; break;
                     case SK_INSERT:             t = term_ki; break;
                     case SK_LITERAL:
                     default:             t = lit; break;
                     }
                     if (t == NULL)
                            return 0;
                     while (*t)
                            To_dst(ISMETA(*s) ? Meta(*t++) : *t++);
                     s += 2;
              }
              else
              {
                     if (ISMETA(*s))
                            To_dst(Meta(*s++));
                     else
                            To_dst(*s++);
              }
       }

       To_dst('\0');

       return 1;

#undef To_dst

}

Here is the caller graph for this function:

static int fetch_user_maps ( void  ) [static]

Definition at line 1455 of file infomap.c.

{
       char *filename = NULL;
       char *homedir;
       int f;
       unsigned char *buf;
       unsigned long len;
       long nread;
       unsigned char *p;
       int n;

       /* Find and open file. */
       if ((filename = getenv("INFOKEY")) != NULL)
              filename = xstrdup(filename);
       else if ((homedir = getenv("HOME")) != NULL)
       {
              filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE));
              strcpy(filename, homedir);
              strcat(filename, "/");
              strcat(filename, INFOKEY_FILE);
       }
#ifdef __MSDOS__
       /* Poor baby, she doesn't have a HOME...  */
       else
              filename = xstrdup(INFOKEY_FILE); /* try current directory */
#endif
       if (filename == NULL || (f = open(filename, O_RDONLY)) == (-1))
       {
              if (filename && errno != ENOENT)
              {
                     info_error(filesys_error_string(filename, errno),
                            NULL, NULL);
                     free(filename);
              }
              return 0;
       }
       SET_BINARY (f);

       /* Ensure that the file is a reasonable size. */
       len = filesize(f);
       if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024)
       {
              /* Bad file (a valid file must have at least 9 chars, and
                 more than 100 KB is a problem). */
              if (len < INFOKEY_NMAGIC + 2)
                     info_error((char *) _("Ignoring invalid infokey file `%s' - too small"),
                               filename, NULL);
              else
                     info_error((char *) _("Ignoring invalid infokey file `%s' - too big"),
                               filename, NULL);
              close(f);
              free(filename);
              return 0;
       }

       /* Read the file into a buffer. */
       buf = (unsigned char *)xmalloc((int)len);
       nread = read(f, buf, (unsigned int) len);
       close(f);
       if ((unsigned int) nread != len)
       {
              info_error((char *) _("Error reading infokey file `%s' - short read"),
                    filename, NULL);
              free(buf);
              free(filename);
              return 0;
       }

       /* Check the header, trailer, and version of the file to increase
          our confidence that the contents are valid.  */
       if (   buf[0] != INFOKEY_MAGIC_S0
              || buf[1] != INFOKEY_MAGIC_S1
              || buf[2] != INFOKEY_MAGIC_S2
              || buf[3] != INFOKEY_MAGIC_S3
              || buf[len - 4] != INFOKEY_MAGIC_E0
              || buf[len - 3] != INFOKEY_MAGIC_E1
              || buf[len - 2] != INFOKEY_MAGIC_E2
              || buf[len - 1] != INFOKEY_MAGIC_E3
       )
       {
              info_error((char *) _("Invalid infokey file `%s' (bad magic numbers) -- run infokey to update it"),
                    filename, NULL);
              free(filename);
              return 0;
       }
       if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1
            || strcmp(VERSION, (char *) (buf + 4)) != 0)
       {
              info_error
                  ((char *) _("Your infokey file `%s' is out of date -- run infokey to update it"),
                    filename, NULL);
              free(filename);
              return 0;
       }

       /* Extract the pieces.  */
       for (p = buf + 4 + strlen(VERSION) + 1;
             (unsigned int) (p - buf) < len - 4;
             p += n)
       {
              int s = *p++;

              n = getint(&p);
              if (n < 0 || (unsigned int) n > len - 4 - (p - buf))
              {
                     info_error((char *) _("Invalid infokey file `%s' (bad section length) -- run infokey to update it"),
                            filename, NULL);
                     free(filename);
                     return 0;
              }

              switch (s)
              {
              case INFOKEY_SECTION_INFO:
                     user_info_keys = p;
                     user_info_keys_len = n;
                     break;
              case INFOKEY_SECTION_EA:
                     user_ea_keys = p;
                     user_ea_keys_len = n;
                     break;
              case INFOKEY_SECTION_VAR:
                     user_vars = p;
                     user_vars_len = n;
                     break;
              default:
                     info_error((char *) _("Invalid infokey file `%s' (bad section code) -- run infokey to update it"),
                            filename, NULL);
                     free(filename);
                     return 0;
              }
       }

       free(filename);
       return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned long filesize ( int  f) [static]

Definition at line 1424 of file infomap.c.

{
       long pos = lseek(f, 0L, SEEK_CUR);
       long sz = -1L;
       if (pos != -1L)
       {
              sz = lseek(f, 0L, SEEK_END);
              lseek(f, pos, SEEK_SET);
       }
       return sz == -1L ? 0L : sz;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FUNCTION_KEYSEQ* find_function_keyseq ( Keymap  map,
int  c,
Keymap  rootmap 
) [static]

Definition at line 67 of file infomap.c.

{
  FUNCTION_KEYSEQ *k;

  if (map[c].type != ISFUNC)
    abort();
  if (map[c].function == NULL)
    return NULL;
  for (k = map[c].function->keys; k; k = k->next)
    {
      const unsigned char *p;
      Keymap m = rootmap;
      if (k->map != rootmap)
       continue;
      for (p = (unsigned char *) k->keyseq; *p && m[*p].type == ISKMAP; p++)
       m = (Keymap)m[*p].function;
      if (*p != c || p[1])
       continue;
      if (m[*p].type != ISFUNC)
       abort ();
      break;
    }
  return k;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int getint ( unsigned char **  sp) [static]

Definition at line 1440 of file infomap.c.

{
       int n;

       if ( !((*sp)[0] < INFOKEY_RADIX && (*sp)[1] < INFOKEY_RADIX) )
              return -1;
       n = (*sp)[0] + (*sp)[1] * INFOKEY_RADIX;
       *sp += 2;
       return n;
}

Here is the caller graph for this function:

Definition at line 1771 of file infomap.c.

{
  int i;
  int suppress_info_default_bindings = 0;
  int suppress_ea_default_bindings = 0;

  if (!info_keymap)
    {
      info_keymap = keymap_make_keymap ();
      echo_area_keymap = keymap_make_keymap ();
    }

  /* Bind the echo area insert routines. */
  for (i = 0; i < 256; i++)
    if (isprint (i))
      echo_area_keymap[i].function = InfoCmd(ea_insert);

  /* Get user-defined keys and variables.  */
  if (fetch_user_maps())
    {
      if (user_info_keys_len && user_info_keys[0])
       suppress_info_default_bindings = 1;
      if (user_ea_keys_len && user_ea_keys[0])
       suppress_ea_default_bindings = 1;
    }

  /* Apply the default bindings, unless the user says to suppress
     them.  */
  if (vi_keys_p)
    {
      if (!suppress_info_default_bindings)
       section_to_keymaps(info_keymap, default_vi_like_info_keys,
                        sizeof(default_vi_like_info_keys));
      if (!suppress_ea_default_bindings)
         section_to_keymaps(echo_area_keymap, default_vi_like_ea_keys,
                          sizeof(default_vi_like_ea_keys));
    }
  else
    {
      if (!suppress_info_default_bindings)
       section_to_keymaps(info_keymap, default_emacs_like_info_keys,
                        sizeof(default_emacs_like_info_keys));
      if (!suppress_ea_default_bindings)
         section_to_keymaps(echo_area_keymap, default_emacs_like_ea_keys,
                          sizeof(default_emacs_like_ea_keys));
    }

  /* If the user specified custom bindings, apply them on top of the
     default ones.  */
  if (user_info_keys_len)
    section_to_keymaps(info_keymap, user_info_keys, user_info_keys_len);

  if (user_ea_keys_len)
    section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len);

  if (user_vars_len)
    section_to_vars(user_vars, user_vars_len);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int keymap_bind_keyseq ( Keymap  map,
const char *  keyseq,
KEYMAP_ENTRY keyentry 
) [static]

Definition at line 205 of file infomap.c.

{
  Keymap m = map;
  const unsigned char *s = (unsigned char *) keyseq;
  int c;

  if (s == NULL || *s == '\0') return 0;

  while ((c = *s++) != '\0')
    {
#if defined(INFOKEY)
      FUNCTION_KEYSEQ *ks;
#endif /* INFOKEY */
      switch (m[c].type)
        {
        case ISFUNC:
#if defined(INFOKEY)
         ks = find_function_keyseq(m, c, map);
         if (ks)
           remove_function_keyseq (m[c].function, ks->keyseq, map);
#else /* !INFOKEY */
          if (!(m[c].function == NULL || (
                m != map &&
                m[c].function == InfoCmd(info_do_lowercase_version))
             ))
            return 0;
#endif /* !INFOKEY */

          if (*s != '\0')
            {
              m[c].type = ISKMAP;
              /* Here we are casting the Keymap pointer returned from
                 keymap_make_keymap to an InfoCommand pointer.  Ugh.
                 This makes the `function' structure garbage
                 if it's actually interpreted as an InfoCommand.
                 Should really be using a union, and taking steps to
                 avoid the possible error.  */
              m[c].function = (InfoCommand *)keymap_make_keymap ();
            }
          break;

        case ISKMAP:
#if defined(INFOKEY)
         if (*s == '\0')
           keymap_discard_keymap ((Keymap)m[c].function, map);
#else /* !INFOKEY */
          if (*s == '\0')
            return 0;
#endif
          break;
        }
      if (*s != '\0')
        {
          m = (Keymap)m[c].function;
        }
      else
        {
#if defined(INFOKEY)
         add_function_keyseq (keyentry->function, keyseq, map);
#endif /* INFOKEY */
          m[c] = *keyentry;
        }
    }

  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Keymap keymap_copy_keymap ( Keymap  map,
Keymap  rootmap,
Keymap  newroot 
)

Definition at line 134 of file infomap.c.

{
  int i;
  Keymap keymap;
#if defined(INFOKEY)
  FUNCTION_KEYSEQ *ks;
#endif /* INFOKEY */

  keymap = keymap_make_keymap ();
  if (!newroot)
    newroot = keymap;

  for (i = 0; i < 256; i++)
    {
      keymap[i].type = map[i].type;
      switch (map[i].type)
       {
       case ISFUNC:
         keymap[i].function = map[i].function;
#if defined(INFOKEY)
         ks = find_function_keyseq (map, i, rootmap);
         if (ks)
           add_function_keyseq(map[i].function, ks->keyseq, newroot);
#endif /* INFOKEY */
         break;
       case ISKMAP:
         keymap[i].function = (InfoCommand *)keymap_copy_keymap
            ((Keymap)map[i].function, rootmap, NULL);
         break;
       }
    }
  return (keymap);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void keymap_discard_keymap ( Keymap  map,
Keymap  rootmap 
)

Definition at line 170 of file infomap.c.

{
  int i;

  if (!map)
    return;
  if (!rootmap)
    rootmap = map;

  for (i = 0; i < 256; i++)
    {
#if defined(INFOKEY)
      FUNCTION_KEYSEQ *ks;
#endif /* INFOKEY */
      switch (map[i].type)
        {
        case ISFUNC:
#if defined(INFOKEY)
         ks = find_function_keyseq(map, i, rootmap);
         if (ks)
           remove_function_keyseq (map[i].function, ks->keyseq, rootmap);
#endif /* INFOKEY */
          break;

        case ISKMAP:
          keymap_discard_keymap ((Keymap)map[i].function, rootmap);
          break;

        }
    }
  free(map);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 39 of file infomap.c.

{
  int i;
  Keymap keymap;

  keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));

  for (i = 0; i < 256; i++)
    {
      keymap[i].type = ISFUNC;
      keymap[i].function = (InfoCommand *)NULL;
    }

  for (i = 'A'; i < ('Z' + 1); i++)
    {
      keymap[i].type = ISFUNC;
#if defined(INFOKEY)
      keymap[Meta(i)].type = ISFUNC;
      keymap[Meta(i)].function =
#endif /* INFOKEY */
      keymap[i].function = InfoCmd(info_do_lowercase_version);
    }

  return (keymap);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void remove_function_keyseq ( InfoCommand function,
const char *  keyseq,
Keymap  rootmap 
) [static]

Definition at line 110 of file infomap.c.

{

  FUNCTION_KEYSEQ *k, *kp;

  if (function == NULL ||
      function == InfoCmd(info_do_lowercase_version) ||
      function == InfoCmd(ea_insert))
    return;
  for (kp = NULL, k = function->keys; k; kp = k, k = k->next)
    if (k->map == rootmap && strcmp(k->keyseq, keyseq) == 0)
      break;
  if (!k)
    abort ();
  if (kp)
    kp->next = k->next;
  else
    function->keys = k->next;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int section_to_keymaps ( Keymap  map,
unsigned char *  table,
unsigned int  len 
) [static]

Definition at line 1657 of file infomap.c.

{
       int stop;
       unsigned char *p;
       unsigned char *seq = NULL;
       unsigned int seqlen = 0;
       enum { getseq, gotseq, getaction } state = getseq;

       stop = len > 0 ? table[0] : 0;

       for (p = table + 1; (unsigned int) (p - table) < len; p++)
       {
              switch (state)
              {
              case getseq:
                     if (*p)
                     {
                            seq = p;
                            state = gotseq;
                     }
                     break;

              case gotseq:
                     if (!*p)
                     {
                            seqlen = p - seq;
                            state = getaction;
                     }
                     break;

              case getaction:
                     {
                            unsigned int action = *p;
                            unsigned char keyseq[256];
                            KEYMAP_ENTRY ke;

                            state = getseq;
                            /* If decode_keys returns zero, it
                               means that seq includes keys which
                               the terminal doesn't support, like
                               PageDown.  In that case, don't bind
                               the key sequence.  */
                            if (decode_keys(seq, seqlen, keyseq,
                                          sizeof keyseq))
                            {
                                   keyseq[sizeof keyseq - 1] = '\0';
                                   ke.type = ISFUNC;
                                   ke.function =
                                     action < A_NCOMMANDS
                                     ? &function_doc_array[action]
                                     : NULL;
                                   keymap_bind_keyseq(map,
                                            (const char *) keyseq, &ke);
                            }
                     }
                     break;
              }
       }
       if (state != getseq)
              info_error((char *) _("Bad data in infokey file -- some key bindings ignored"),
                    NULL, NULL);
       return !stop;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void section_to_vars ( unsigned char *  table,
unsigned int  len 
) [static]

Definition at line 1724 of file infomap.c.

{
       enum { getvar, gotvar, getval, gotval } state = getvar;
       unsigned char *var = NULL;
       unsigned char *val = NULL;
       unsigned char *p;

       for (p = table; (unsigned int) (p - table) < len; p++)
         {
           switch (state)
             {
             case getvar:
              if (*p)
                {
                  var = p;
                  state = gotvar;
                }
              break;

             case gotvar:
              if (!*p)
                state = getval;
              break;

             case getval:
              if (*p)
                {
                  val = p;
                  state = gotval;
                }
              break;

             case gotval:
              if (!*p)
                {
                  set_variable_to_value((char *) var, (char *) val);
                  state = getvar;
                }
              break;
             }
         }
      if (state != getvar)
       info_error((char *) _("Bad data in infokey file -- some var settings ignored"),
            NULL, NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

unsigned char default_emacs_like_ea_keys[] [static]

Definition at line 1008 of file infomap.c.

unsigned char default_emacs_like_info_keys[] [static]

Definition at line 849 of file infomap.c.

unsigned char default_vi_like_ea_keys[] [static]

Definition at line 1299 of file infomap.c.

unsigned char default_vi_like_info_keys[] [static]

Definition at line 1111 of file infomap.c.

Definition at line 276 of file infomap.c.

Definition at line 275 of file infomap.c.

unsigned char* user_ea_keys [static]

Definition at line 1415 of file infomap.c.

unsigned int user_ea_keys_len [static]

Definition at line 1416 of file infomap.c.

unsigned char* user_info_keys [static]

Definition at line 1413 of file infomap.c.

unsigned int user_info_keys_len [static]

Definition at line 1414 of file infomap.c.

unsigned char* user_vars [static]

Definition at line 1417 of file infomap.c.

unsigned int user_vars_len [static]

Definition at line 1418 of file infomap.c.