Annotation of 43BSD/contrib/emacs/src/keymap.c, revision 1.1.1.1

1.1       root        1: /* Manipulation of keymaps
                      2:    Copyright (C) 1985 Richard M. Stallman.
                      3: 
                      4: This file is part of GNU Emacs.
                      5: 
                      6: GNU Emacs is distributed in the hope that it will be useful,
                      7: but WITHOUT ANY WARRANTY.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.  Refer to the GNU Emacs General Public
                     11: License for full details.
                     12: 
                     13: Everyone is granted permission to copy, modify and redistribute
                     14: GNU Emacs, but only under the conditions described in the
                     15: GNU Emacs General Public License.   A copy of this license is
                     16: supposed to have been given to you along with GNU Emacs so you
                     17: can know your rights and responsibilities.  It should be in a
                     18: file named COPYING.  Among other things, the copyright notice
                     19: and this notice must be preserved on all copies.  */
                     20: 
                     21: 
                     22: #include "config.h"
                     23: #include <stdio.h>
                     24: #undef NULL
                     25: #include "lisp.h"
                     26: #include "commands.h"
                     27: #include "buffer.h"
                     28: 
                     29: /* Actually allocate storage for these variables */
                     30: 
                     31: #ifdef HAVE_X_WINDOWS
                     32: struct Lisp_Vector *MouseMap;          /* Keymap for mouse commands */
                     33: #endif /* HAVE_X_WINDOWS */
                     34: 
                     35: struct Lisp_Vector *CurrentGlobalMap;  /* Current global keymap */
                     36: 
                     37: struct Lisp_Vector *GlobalMap; /* default global key bindings */
                     38: 
                     39: struct Lisp_Vector *ESCmap;            /* The keymap used for globally
                     40:                                           bound ESC-prefixed default
                     41:                                           commands */
                     42: 
                     43: struct Lisp_Vector *CtlXmap;           /* The keymap used for globally
                     44:                                           bound C-x-prefixed default
                     45:                                           commands */
                     46: 
                     47: /* was MinibufLocalMap */
                     48: Lisp_Object Vminibuffer_local_map;
                     49:                                /* The keymap used by the minibuf for local
                     50:                                   bindings when spaces are allowed in the
                     51:                                   minibuf */
                     52: 
                     53: /* was MinibufLocalNSMap */
                     54: Lisp_Object Vminibuffer_local_ns_map;                  
                     55:                                /* The keymap used by the minibuf for local
                     56:                                   bindings when spaces are not encouraged
                     57:                                   in the minibuf */
                     58: 
                     59: /* keymap used for minibuffers when doing completion */
                     60: /* was MinibufLocalCompletionMap */
                     61: Lisp_Object Vminibuffer_local_completion_map;
                     62: 
                     63: /* keymap used for minibuffers when doing completion and require a match */
                     64: /* was MinibufLocalMustMatchMap */
                     65: Lisp_Object Vminibuffer_local_must_match_map;
                     66: 
                     67: Lisp_Object Qkeymapp, Qkeymap;
                     68: 
                     69: DEFUN ("make-keymap", Fmake_keymap, Smake_keymap, 0, 0, 0,
                     70:   "Construct and return a new keymap, a vector of length 128.\n\
                     71: All entries in it are nil, meaning \"command undefined\".")
                     72:   ()
                     73: {
                     74:   Lisp_Object val;
                     75:   XFASTINT (val) = 0200;
                     76:   return Fmake_vector (val, Qnil);
                     77: }
                     78: 
                     79: DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, Smake_sparse_keymap, 0, 0, 0,
                     80:   "Construct and return a new sparse-keymap list.\n\
                     81: Its car is 'keymap and its cdr is an alist of (CHAR . DEFINITION).\n\
                     82: Initially the alist is nil.")
                     83:   ()
                     84: {
                     85:   return Fcons (Qkeymap, Qnil);
                     86: }
                     87: 
                     88: /* This is used for installing the standard key bindings at initialization time.
                     89:  For example,  defkey (CtlXmap, Ctl('X'), "exchange-point-and-mark");  */
                     90: 
                     91: void
                     92: defkey (keymap, key, defname)
                     93:      struct Lisp_Vector *keymap;
                     94:      int key;
                     95:      char *defname;
                     96: {
                     97:   keymap->contents[key] = intern (defname);
                     98: }
                     99: 
                    100: void
                    101: ndefkey (keymap, key, defname)
                    102:      Lisp_Object keymap;
                    103:      int key;
                    104:      char *defname;
                    105: {
                    106:   store_in_keymap (keymap, key, intern (defname));
                    107: }
                    108: 
                    109: /* Define character fromchar in map frommap as an alias for character tochar in map tomap.
                    110:  Subsequent redefinitions of the latter WILL affect the former. */
                    111: 
                    112: #ifdef NOTDEF
                    113: void
                    114: synkey (frommap, fromchar, tomap, tochar)
                    115:      struct Lisp_Vector *frommap, *tomap;
                    116:      int fromchar, tochar;
                    117: {
                    118:   Lisp_Object v, c;
                    119:   XSET (v, Lisp_Vector, tomap);
                    120:   XFASTINT (c) = tochar;
                    121:   frommap->contents[fromchar] = Fcons (v, c);
                    122: }
                    123: #endif /* NOTDEF */
                    124: 
                    125: DEFUN ("keymapp", Fkeymapp, Skeymapp, 1, 1, 0,
                    126:   "Return t if ARG is a keymap.\n\
                    127: A keymap is a vector of length 128, or a list (keymap . ALIST),\n\
                    128: where alist elements look like (CHAR . DEFN).")
                    129:   (object)
                    130:      Lisp_Object object;
                    131: {
                    132:   Lisp_Object tem;
                    133:   tem = object;
                    134:   while (XTYPE (tem) == Lisp_Symbol)
                    135:     {
                    136:       tem = XSYMBOL (tem)->function;
                    137:       if (EQ (tem, Qunbound))
                    138:        return Qnil;
                    139:     }
                    140: 
                    141:   if ((XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == 0200)
                    142:       || (LISTP (tem) && EQ (XCONS (tem)->car, Qkeymap)))
                    143:     return Qt;
                    144:   return Qnil;
                    145: }
                    146: 
                    147: Lisp_Object
                    148: get_keymap (object, argnumber)
                    149:      Lisp_Object object;
                    150:      int argnumber;
                    151: {
                    152:   Lisp_Object tem;
                    153: 
                    154:   while (1)
                    155:     {
                    156:       tem = object;
                    157:       while (XTYPE (tem) == Lisp_Symbol && !EQ (tem, Qunbound))
                    158:        tem = XSYMBOL (tem)->function;
                    159: 
                    160:       if ((XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == 0200)
                    161:          || (LISTP (tem) && EQ (XCONS (tem)->car, Qkeymap)))
                    162:        return tem;
                    163:       if (argnumber >= 0)
                    164:        object = wrong_type_argument (Qkeymapp, object);
                    165:       else return Qnil;
                    166:     }
                    167: }
                    168: 
                    169: Lisp_Object
                    170: get_keyelt (object)
                    171:      Lisp_Object object;
                    172: {
                    173:   Lisp_Object map, tem;
                    174: 
                    175:   while (map = get_keymap (Fcar_safe (object), -1),
                    176:         tem = Fkeymapp (map),
                    177:         !NULL (tem))
                    178:       /*(XTYPE (object) == Lisp_Cons && !EQ (XCONS (object)->car, Qkeymap))*/
                    179:     {
                    180:       object = Fcdr (object);
                    181:       if (LISTP (map))
                    182:        object = Fcdr (Fassq (object, Fcdr (map)));
                    183:       else
                    184:        object = Faref (map, object);
                    185:     }
                    186:   return object;
                    187: }
                    188: 
                    189: Lisp_Object
                    190: access_keymap (map, idx)
                    191:      Lisp_Object map;
                    192:      register int idx;
                    193: {
                    194:   register Lisp_Object val;
                    195:   if (idx < 0 || idx >= 0200)
                    196:     error ("Command key out of range 0-127");
                    197: 
                    198:   /* Get definition for character `idx' proper.  */
                    199:   if (LISTP (map))
                    200:     val = Fcdr (Fassq (make_number (idx), Fcdr (map)));
                    201:   else
                    202:     val = XVECTOR (map)->contents[idx];
                    203: 
                    204:   /* If nothing there, and `idx' is upper case,
                    205:      look under corresponding lower case character.  */
                    206: 
                    207:   if (NULL (val) && idx >= 'A' && idx <= 'Z')
                    208:     {
                    209:       if (LISTP (map))
                    210:        val = Fcdr (Fassq (make_number (idx + 'a' - 'A'), Fcdr (map)));
                    211:       else
                    212:        val = XVECTOR (map)->contents[idx + 'a' - 'A'];
                    213:     }
                    214:   return val;
                    215: }
                    216: 
                    217: Lisp_Object
                    218: store_in_keymap (keymap, idx, def)
                    219:      Lisp_Object keymap;
                    220:      int idx;
                    221:      Lisp_Object def;
                    222: {
                    223:   Lisp_Object tem;
                    224: 
                    225:   if (idx < 0 || idx >= 0200)
                    226:     error ("Command key out of range 0-127");
                    227: 
                    228:   if (LISTP (keymap))
                    229:     {
                    230:       tem = Fassq (make_number (idx), Fcdr (keymap));
                    231:       if (!NULL (tem))
                    232:        Fsetcdr (tem, def);
                    233:       else
                    234:        Fsetcdr (keymap, Fcons (Fcons (make_number (idx), def),
                    235:                                Fcdr (keymap)));
                    236:     }
                    237:   else
                    238:     XVECTOR (keymap)->contents[idx] = def;
                    239: 
                    240:   return def;
                    241: }
                    242: 
                    243: DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0,
                    244:   "Args KEYMAP, KEYS, DEF.  Define key sequence KEYS, in KEYMAP, as DEF.\n\
                    245: KEYMAP is a keymap.  KEYS is a string meaning a sequence of keystrokes.\n\
                    246: DEF is usually a symbol with a function definition, suitable for use as a command.")
                    247:   (keymap, keys, def)
                    248:      Lisp_Object keymap;
                    249:      Lisp_Object keys;
                    250:      Lisp_Object def;
                    251: {
                    252:   unsigned char *p;
                    253:   int level;
                    254:   Lisp_Object tem;
                    255:   Lisp_Object cmd;
                    256: 
                    257:   keymap = get_keymap (keymap, 0);
                    258: 
                    259:   CHECK_STRING (keys, 1);
                    260:   p = XSTRING (keys)->data;
                    261:   level = XSTRING (keys)->size;
                    262: 
                    263:   while (1)
                    264:     {
                    265:       level--;
                    266: 
                    267:       if (!level)
                    268:        return store_in_keymap (keymap, *p, def);
                    269: 
                    270:       cmd = get_keyelt (access_keymap (keymap, *p));
                    271:       if (NULL (cmd))
                    272:        {
                    273:          cmd = Fmake_sparse_keymap ();
                    274:          store_in_keymap (keymap, *p, cmd);
                    275:        }
                    276:       tem = Fkeymapp (cmd);
                    277:       if (NULL (tem))
                    278:        error ("Key sequence %s uses invalid prefix characters",
                    279:               XSTRING (keys)->data);
                    280: 
                    281:       keymap = get_keymap (cmd, 0);
                    282:       p++;
                    283:     }
                    284: }
                    285: 
                    286: /* Value is T if `keys' is too long; NIL if valid but has no definition. */
                    287: 
                    288: DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 2, 0,
                    289:   "In keymap KEYMAP, look up key sequence KEYS.  Return the definition.\n\
                    290: nil means undefined.\n\
                    291: Number as value means KEYS is \"too long\";\n\
                    292: that is, characters in it except for the last one\n\
                    293: fail to be a valid sequence of prefix characters in KEYMAP.\n\
                    294: The number is how many characters at the front of KEYS\n\
                    295: it takes to reach a non-prefix command.")
                    296:   (keymap, keys)
                    297:      Lisp_Object keymap;
                    298:      Lisp_Object keys;
                    299: {
                    300:   unsigned char *p;
                    301:   int level;
                    302:   Lisp_Object tem;
                    303:   Lisp_Object cmd;
                    304: 
                    305:   keymap = get_keymap (keymap, 0);
                    306: 
                    307:   CHECK_STRING (keys, 1);
                    308:   p = XSTRING (keys)->data;
                    309:   level = XSTRING (keys)->size;
                    310: 
                    311:   while (1)
                    312:     {
                    313:       level--;
                    314:       cmd = get_keyelt (access_keymap (keymap, *p++));
                    315:       if (!level)
                    316:        return cmd;
                    317: 
                    318:       tem = Fkeymapp (cmd);
                    319:       if (NULL (tem))
                    320:        return make_number (XSTRING (keys)->size - level);
                    321: 
                    322:       keymap = get_keymap (cmd, 0);
                    323:     }
                    324: }
                    325: 
                    326: DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 1, 0,
                    327:   "Return the definition for command KEYS in current keymaps.\n\
                    328: KEYS is a string, a sequence of keystrokes.\n\
                    329: The definition is probably a symbol with a function definition.")
                    330:   (keys)
                    331:      Lisp_Object keys;
                    332: {
                    333:   Lisp_Object map, value, value1;
                    334:   map = bf_cur->keymap;
                    335:   if (!NULL (map))
                    336:     {
                    337:       value = Flookup_key (map, keys);
                    338:       if (NULL (value))
                    339:        {
                    340:          XSET (map, Lisp_Vector, CurrentGlobalMap);
                    341:          value1 = Flookup_key (map, keys);
                    342:          if (XTYPE (value1) == Lisp_Int)
                    343:            return Qnil;
                    344:          return value1;
                    345:        }
                    346:       else if (XTYPE (value) != Lisp_Int)
                    347:        return value;
                    348:     }
                    349:   XSET (map, Lisp_Vector, CurrentGlobalMap);
                    350:   return Flookup_key (map, keys);
                    351: }
                    352: 
                    353: DEFUN ("local-key-binding", Flocal_key_binding, Slocal_key_binding, 1, 1, 0,
                    354:   "Return the definition for command KEYS in current local keymap only.\n\
                    355: KEYS is a string, a sequence of keystrokes.\n\
                    356: The definition is probably a symbol with a function definition.")
                    357:   (keys)
                    358:      Lisp_Object keys;
                    359: {
                    360:   Lisp_Object map;
                    361:   map = bf_cur->keymap;
                    362:   if (NULL (map))
                    363:     return Qnil;
                    364:   return Flookup_key (map, keys);
                    365: }
                    366: 
                    367: DEFUN ("global-key-binding", Fglobal_key_binding, Sglobal_key_binding, 1, 1, 0,
                    368:   "Return the definition for command KEYS in current global keymap only.\n\
                    369: KEYS is a string, a sequence of keystrokes.\n\
                    370: The definition is probably a symbol with a function definition.")
                    371:   (keys)
                    372:      Lisp_Object keys;
                    373: {
                    374:   Lisp_Object map;
                    375:   XSET (map, Lisp_Vector, CurrentGlobalMap);
                    376:   return Flookup_key (map, keys);
                    377: }
                    378: 
                    379: DEFUN ("global-set-key", Fglobal_set_key, Sglobal_set_key, 2, 2,
                    380:   "kSet key globally: \nCSet key %s to command: ",
                    381:   "Give KEY a definition of COMMAND.\n\
                    382: COMMAND is a symbol naming an interactively-callable function.\n\
                    383: KEY is a string representing a sequence of keystrokes.\n\
                    384: Note that if KEY has a local definition in the current buffer\n\
                    385: that local definition will continue to shadow any global definition.")
                    386:   (keys, function)
                    387:      Lisp_Object keys, function;
                    388: {
                    389:   Lisp_Object map;
                    390:   XSET (map, Lisp_Vector, CurrentGlobalMap);
                    391:   CHECK_STRING (keys, 1);
                    392:   Fdefine_key (map, keys, function);
                    393:   return Qnil;
                    394: }
                    395: 
                    396: DEFUN ("local-set-key", Flocal_set_key, Slocal_set_key, 2, 2,
                    397:   "kSet key locally: \nCSet key %s locally to command: ",
                    398:   "Give KEY a local definition of COMMAND.\n\
                    399: COMMAND is a symbol naming an interactively-callable function.\n\
                    400: KEY is a string representing a sequence of keystrokes.\n\
                    401: The definition goes in the current buffer's local map,\n\
                    402: which is shared with other buffers in the same major mode.")
                    403:   (keys, function)
                    404:      Lisp_Object keys, function;
                    405: {
                    406:   Lisp_Object map;
                    407:   map = bf_cur->keymap;
                    408:   if (NULL (map))
                    409:     {
                    410:       map = Fmake_sparse_keymap ();
                    411:       bf_cur->keymap = map;
                    412:     }
                    413: 
                    414:   CHECK_STRING (keys, 1);
                    415:   Fdefine_key (map, keys, function);
                    416:   return Qnil;
                    417: }
                    418: 
                    419: DEFUN ("global-unset-key", Fglobal_unset_key, Sglobal_unset_key,
                    420:   1, 1, "kUnset key globally: ",
                    421:   "Remove global definition of KEY.\n\
                    422: KEY is a string representing a sequence of keystrokes.")
                    423:   (keys)
                    424:      Lisp_Object keys;
                    425: {
                    426:   return Fglobal_set_key (keys, Qnil);
                    427: }
                    428: 
                    429: DEFUN ("local-unset-key", Flocal_unset_key, Slocal_unset_key, 1, 1,
                    430:   "kUnset key locally: ",
                    431:   "Remove local definition of KEY.\n\
                    432: KEY is a string representing a sequence of keystrokes.")
                    433:   (keys)
                    434:      Lisp_Object keys;
                    435: {
                    436:   if (!NULL (bf_cur->keymap))
                    437:     Flocal_set_key (keys, Qnil);
                    438:   return Qnil;
                    439: }
                    440: 
                    441: DEFUN ("define-prefix-command", Fdefine_prefix_command, Sdefine_prefix_command, 1, 1, 0,
                    442:   "Define SYMBOL as a prefix command.\n\
                    443: A keymap is created and stored as SYMBOL's function definition.")
                    444:   (name)
                    445:      Lisp_Object name;
                    446: {
                    447:   Fset (name, Fmake_keymap ());
                    448:   return name;
                    449: }
                    450: 
                    451: DEFUN ("use-global-map", Fuse_global_map, Suse_global_map, 1, 1, 0,
                    452:   "Selects KEYMAP as the global keymap.")
                    453:   (keymap)
                    454:      Lisp_Object keymap;
                    455: {
                    456:   keymap = get_keymap (keymap, 0);
                    457:   CHECK_VECTOR (keymap, 0);
                    458:   CurrentGlobalMap = XVECTOR (keymap);
                    459:   return Qnil;
                    460: }
                    461: 
                    462: DEFUN ("use-local-map", Fuse_local_map, Suse_local_map, 1, 1, 0,
                    463:   "Selects KEYMAP as the local keymap.\n\
                    464: nil for KEYMAP means no local keymap.")
                    465:   (keymap)
                    466:      Lisp_Object keymap;
                    467: {
                    468:   if (!NULL (keymap))
                    469:     keymap = get_keymap (keymap, 0);
                    470: 
                    471:   bf_cur->keymap = keymap;
                    472: 
                    473:   return Qnil;
                    474: }
                    475: 
                    476: DEFUN ("current-local-map", Fcurrent_local_map, Scurrent_local_map, 0, 0, 0,
                    477:   "Return current buffer's local keymap, or nil if it has none.")
                    478:   ()
                    479: {
                    480:   return bf_cur->keymap;
                    481: }
                    482: 
                    483: DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
                    484:   1, 1, 0,
                    485:   "Find all keymaps accessible via prefix characters from KEYMAP.\n\
                    486: Returns a list of elements of the form (KEYS . MAP), where the sequence\n\
                    487: KEYS starting from KEYMAP gets you to MAP.  These elements are ordered\n\
                    488: so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
                    489:   (startmap)
                    490:      Lisp_Object startmap;
                    491: {
                    492:   Lisp_Object maps, tail;
                    493:   Lisp_Object thismap, thisseq;
                    494:   Lisp_Object dummy;
                    495:   Lisp_Object tem;
                    496:   Lisp_Object cmd;
                    497:   int i;
                    498: 
                    499:   maps = Fcons (Fcons (build_string (""), get_keymap (startmap, 0)), Qnil);
                    500:   tail = maps;
                    501: 
                    502:   /* For each map in the list maps,
                    503:      look at any other maps it points to
                    504:      and stick them at the end if they are not already in the list */
                    505: 
                    506:   while (!NULL (tail))
                    507:     {
                    508:       thisseq = Fcar (Fcar (tail));
                    509:       thismap = Fcdr (Fcar (tail));
                    510:       for (i = 0; i < 0200; i++)
                    511:        {
                    512:          cmd = get_keyelt (access_keymap (thismap, i));
                    513:          if (NULL (cmd)) continue;
                    514:          tem = Fkeymapp (cmd);
                    515:          if (!NULL (tem))
                    516:            {
                    517:                cmd = get_keymap (cmd, 0);
                    518:                tem = Frassq (cmd, maps);
                    519:                if (NULL (tem)) {
                    520:                      XFASTINT (dummy) = i;
                    521:                      dummy = concat2 (thisseq, Fchar_to_string (dummy));
                    522:                      nconc2 (tail, Fcons (Fcons (dummy, cmd), Qnil));
                    523:                }
                    524:            }
                    525:        }
                    526:       tail = Fcdr (tail);
                    527:     }
                    528: 
                    529:   return maps;
                    530: }
                    531: 
                    532: Lisp_Object Qsingle_key_description, Qkey_description;
                    533: 
                    534: DEFUN ("key-description", Fkey_description, Skey_description, 1, 1, 0,
                    535:   "Return a pretty description of key-sequence KEYS.\n\
                    536: Control characters turn into \"C-foo\" sequences, meta into \"M-foo\"\n\
                    537: spaces are put between sequence elements, etc.")
                    538:   (keys)
                    539:      Lisp_Object keys;
                    540: {
                    541:   return Fmapconcat (Qsingle_key_description, keys, build_string (" "));
                    542: }
                    543: 
                    544: char *
                    545: push_key_description (c, p)
                    546:      register unsigned int c;
                    547:      register char *p;
                    548: {
                    549:   if (c >= 0200)
                    550:     {
                    551:       *p++ = 'M';
                    552:       *p++ = '-';
                    553:       c -= 0200;
                    554:     }
                    555:   if (c < 040)
                    556:     {
                    557:       if (c == 033)
                    558:        {
                    559:          *p++ = 'E';
                    560:          *p++ = 'S';
                    561:          *p++ = 'C';
                    562:        }
                    563:       else if (c == Ctl('I'))
                    564:        {
                    565:          *p++ = 'T';
                    566:          *p++ = 'A';
                    567:          *p++ = 'B';
                    568:        }
                    569:       else if (c == Ctl('J'))
                    570:        {
                    571:          *p++ = 'L';
                    572:          *p++ = 'F';
                    573:          *p++ = 'D';
                    574:        }
                    575:       else if (c == Ctl('M'))
                    576:        {
                    577:          *p++ = 'R';
                    578:          *p++ = 'E';
                    579:          *p++ = 'T';
                    580:        }
                    581:       else
                    582:        {
                    583:          *p++ = 'C';
                    584:          *p++ = '-';
                    585:          if (c > 0 && c <= Ctl ('Z'))
                    586:            *p++ = c + 0140;
                    587:          else
                    588:            *p++ = c + 0100;
                    589:        }
                    590:     }
                    591:   else if (c == 0177)
                    592:     {
                    593:       *p++ = 'D';
                    594:       *p++ = 'E';
                    595:       *p++ = 'L';
                    596:     }
                    597:   else if (c == ' ')
                    598:     {
                    599:       *p++ = 'S';
                    600:       *p++ = 'P';
                    601:       *p++ = 'C';
                    602:     }
                    603:   else
                    604:     *p++ = c;
                    605:   return p;  
                    606: }
                    607: 
                    608: DEFUN ("single-key-description", Fsingle_key_description, Ssingle_key_description, 1, 1, 0,
                    609:   "Return a pretty description of command character KEY.\n\
                    610: Control characters turn into C-whatever, etc.")
                    611:   (key)
                    612:      Lisp_Object key;
                    613: {
                    614:   unsigned char c;
                    615:   char tem[6];
                    616: 
                    617:   CHECK_NUMBER (key, 0);
                    618:   c = XINT (key) & 0377;
                    619: 
                    620:   *push_key_description (c, tem) = 0;
                    621: 
                    622:   return build_string (tem);
                    623: }
                    624: 
                    625: char *
                    626: push_text_char_description (c, p)
                    627:      register unsigned int c;
                    628:      register char *p;
                    629: {
                    630:   if (c >= 0200)
                    631:     {
                    632:       *p++ = 'M';
                    633:       *p++ = '-';
                    634:       c -= 0200;
                    635:     }
                    636:   if (c < 040)
                    637:     {
                    638:       *p++ = '^';
                    639:       *p++ = c + 64;           /* 'A' - 1 */
                    640:     }
                    641:   else if (c == 0177)
                    642:     {
                    643:       *p++ = '^';
                    644:       *p++ = '?';
                    645:     }
                    646:   else
                    647:     *p++ = c;
                    648:   return p;  
                    649: }
                    650: 
                    651: DEFUN ("text-char-description", Ftext_char_description, Stext_char_description, 1, 1, 0,
                    652:   "Return a pretty description of file-character CHAR.\n\
                    653: Control characters turn into \"C-char\", etc.")
                    654:   (chr)
                    655:      Lisp_Object chr;
                    656: {
                    657:   char tem[6];
                    658: 
                    659:   CHECK_NUMBER (chr, 0);
                    660: 
                    661:   *push_text_char_description (XINT (chr) & 0377, tem) = 0;
                    662: 
                    663:   return build_string (tem);
                    664: }
                    665: 
                    666: Lisp_Object where_is_in_buffer ();
                    667: 
                    668: DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 1, 0,
                    669:   "Return list of key sequences that currently invoke command DEFINITION.")
                    670:   (definition)
                    671:      Lisp_Object definition;
                    672: {
                    673:   return where_is_in_buffer (definition, bf_cur, 0);
                    674: }
                    675: 
                    676: Lisp_Object
                    677: where_is_in_buffer (definition, buf, firstonly)
                    678:      Lisp_Object definition;
                    679:      struct buffer *buf;
                    680:      int firstonly;            /* if true, return after finding one */
                    681: {
                    682:   Lisp_Object start1, start2;
                    683:   Lisp_Object maps;
                    684:   Lisp_Object this, map;
                    685:   Lisp_Object dummy;
                    686:   Lisp_Object found;
                    687:   Lisp_Object tem;
                    688:   register int i;
                    689: 
                    690:   XSET (start1, Lisp_Vector, CurrentGlobalMap);
                    691:   start2 = buf->keymap;
                    692: 
                    693:   if (!NULL (start2))
                    694:     maps = nconc2 (Faccessible_keymaps (start2),
                    695:                   Faccessible_keymaps (start1));
                    696:   else
                    697:     maps = Faccessible_keymaps (start1);
                    698: 
                    699:   found = Qnil;
                    700: 
                    701:   for (; !NULL (maps); maps = Fcdr (maps))
                    702:     {
                    703:       this = Fcar (Fcar (maps));       /* Key sequence to reach map */
                    704:       map = Fcdr (Fcar (maps));                /* The map that it reaches */
                    705:       if (LISTP (map))
                    706:        for (map = Fcdr (map); !NULL (map); map = Fcdr (map))
                    707:          {
                    708:            QUIT;
                    709:            tem = Fcdr (Fcar (map));
                    710:            if (EQ (tem, definition))
                    711:              {
                    712:                dummy = Fcar (Fcar (map));
                    713:                dummy = concat2 (this, Fchar_to_string (dummy));
                    714:                if (firstonly)
                    715:                  return dummy;
                    716:                found = Fcons (dummy, found);
                    717:              }
                    718:          }
                    719:       else
                    720:        for (i = 0; i < 0200; i++)      /* Search that map for a match */
                    721:          {
                    722:            QUIT;
                    723:            tem = XVECTOR (map)->contents[i];
                    724:            if (EQ (tem, definition))   /* Match found: record key sequence */
                    725:              {
                    726:                XFASTINT (dummy) = i;   /* which is `this' followed by character i */
                    727:                dummy = concat2 (this, Fchar_to_string (dummy));
                    728:                if (firstonly)
                    729:                  return dummy;
                    730:                found = Fcons (dummy, found);
                    731:              }
                    732:          }
                    733:     }
                    734:   return Fnreverse (found);
                    735: }
                    736: 
                    737: DEFUN ("where-is", Fwhere_is, Swhere_is, 1, 1, "CWhere is command: ",
                    738:   "Print message listing key sequences that invoke specified command.\n\
                    739: Argument is a command definition, usually a symbol with a function definition.")
                    740:   (definition)
                    741:      Lisp_Object definition;
                    742: {
                    743:   Lisp_Object tem;
                    744:   CHECK_SYMBOL (definition, 0);
                    745:   tem = Fmapconcat (Qkey_description, Fwhere_is_internal (definition), build_string (", "));
                    746:   if (XSTRING (tem)->size)
                    747:     message ("%s is on %s", XSYMBOL (definition)->name->data, XSTRING (tem)->data);
                    748:   else
                    749:     message ("%s is not on any keys", XSYMBOL (definition)->name->data);
                    750:   return Qnil;
                    751: }
                    752: 
                    753: Lisp_Object describe_buffer_bindings ();
                    754: 
                    755: DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 0, "",
                    756:   "Show a list of all defined keys, and their definitions.\n\
                    757: The list is put in a buffer, which is displayed.")
                    758:   ()
                    759: {
                    760:   Lisp_Object thisbuf;
                    761:   XSETTYPE (thisbuf, Lisp_Buffer), XSETBUFFER (thisbuf, bf_cur);
                    762:   internal_with_output_to_temp_buffer ("*Help*", describe_buffer_bindings, thisbuf);
                    763:   return Qnil;
                    764: }
                    765: 
                    766: Lisp_Object
                    767: describe_buffer_bindings (descbuf)
                    768:      Lisp_Object descbuf;
                    769: {
                    770:   register Lisp_Object start1;
                    771:   char *heading = "key         binding\n---            -------\n";
                    772: 
                    773:   Fset_buffer (Vstandard_output);
                    774: 
                    775:   start1 = XBUFFER (descbuf)->keymap;
                    776:   if (!NULL (start1))
                    777:     {
                    778:       InsStr ("Local Bindings:\n");
                    779:       InsStr (heading);
                    780:       heading = 0;
                    781:       describe_map_tree (start1, 0);
                    782:       InsStr ("\n");
                    783:     }
                    784: 
                    785:   InsStr ("Global Bindings:\n");
                    786:   if (heading)
                    787:     InsStr (heading);
                    788: 
                    789:   XSET (start1, Lisp_Vector, CurrentGlobalMap);
                    790:   describe_map_tree (start1, 0);
                    791: 
                    792:   Fset_buffer (descbuf);
                    793:   return Qnil;
                    794: }
                    795: 
                    796: /* Insert a desription of the key bindings in STARTMAP,
                    797:    followed by those of all maps reachable through STARTMAP.
                    798:    If PARTIAL is nonzero, omit certain "uninteresting" commands
                    799:    (such as `undefined').  */
                    800: 
                    801: describe_map_tree (startmap, partial)
                    802:      Lisp_Object startmap;
                    803:      int partial;
                    804: {
                    805:   register Lisp_Object maps, elt;
                    806: 
                    807:   maps = Faccessible_keymaps (startmap);
                    808: 
                    809:   for (; !NULL (maps); maps = Fcdr (maps))
                    810:     {
                    811:       elt = Fcar (maps);
                    812:       describe_map (Fcdr (elt), Fcar (elt), partial);
                    813:     }
                    814: }
                    815: 
                    816: describe_command (definition)
                    817:      Lisp_Object definition;
                    818: {
                    819:   register Lisp_Object tem1;
                    820: 
                    821:   if (XTYPE (definition) == Lisp_Symbol)
                    822:     {
                    823:       XSETSTRING (tem1, XSYMBOL (definition)->name);
                    824:       InsCStr (XSTRING (tem1)->data, XSTRING (tem1)->size);
                    825:     }
                    826:   else
                    827:     {
                    828:       tem1 = Fkeymapp (definition);
                    829:       if (!NULL (tem1))
                    830:        InsStr ("Prefix Command");
                    831:       else
                    832:        InsStr ("??");
                    833:     }
                    834: }
                    835: 
                    836: /* Describe the contents of map MAP, assuming that this map
                    837:    itself is reached by the sequence of prefix keys KEYS (a string).
                    838:    PARTIAL is the same as in `describe_map_tree', above.  */
                    839: 
                    840: describe_map (map, keys, partial)
                    841:      Lisp_Object map, keys;
                    842:      int partial;
                    843: {
                    844:   register Lisp_Object keysdesc;
                    845: 
                    846:   InsStr ("\n");
                    847: 
                    848:   if (!NULL (keys) && XSTRING (keys)->size > 0)
                    849:     keysdesc = Fkey_description (keys);
                    850:   else
                    851:     keysdesc = Qnil;
                    852: 
                    853:   if (LISTP (map))
                    854:     describe_alist (Fcdr (map), keysdesc, describe_command, partial);
                    855:   else
                    856:     describe_vector (map, keysdesc, describe_command, partial);
                    857: }
                    858: 
                    859: describe_alist (alist, elt_prefix, elt_describer, partial)
                    860:      register Lisp_Object alist;
                    861:      register Lisp_Object elt_prefix;
                    862:      int (*elt_describer) ();
                    863:      int partial;
                    864: {
                    865:   Lisp_Object this;
                    866:   register Lisp_Object tem1, tem2;
                    867:   int indent;
                    868:   Lisp_Object suppress;
                    869: 
                    870:   if (partial)
                    871:     suppress = intern ("suppress-keymap");
                    872: 
                    873:   for (; LISTP (alist); alist = Fcdr (alist))
                    874:     {
                    875:       QUIT;
                    876:       tem1 = Fcar (Fcar (alist));
                    877:       tem2 = Fcdr (Fcar (alist));
                    878:       if (NULL (tem2)) continue;      
                    879:       if (XTYPE (tem2) == Lisp_Symbol && partial)
                    880:        {
                    881:          this = Fget (tem2, suppress);
                    882:          if (!NULL (this))
                    883:            continue;
                    884:        }
                    885: 
                    886:       indent = 0;
                    887: 
                    888:       if (!NULL (elt_prefix))
                    889:        {
                    890:          InsCStr (XSTRING (elt_prefix)->data, XSTRING (elt_prefix)->size);
                    891:          InsCStr (" ", 1);
                    892:          indent += XSTRING (elt_prefix)->size + 1;
                    893:        }
                    894: 
                    895:       this = Fsingle_key_description (tem1);
                    896:       InsCStr (XSTRING (this)->data, XSTRING (this)->size);
                    897:       indent += XSTRING (this)->size;
                    898: 
                    899:       InsCStr ("                    ", indent<16 ? 16-indent : 1);
                    900: 
                    901:       (*elt_describer) (tem2);
                    902:       InsCStr ("\n", 1);
                    903:     }
                    904: }
                    905: 
                    906: describe_vector (vector, elt_prefix, elt_describer, partial)
                    907:      register Lisp_Object vector;
                    908:      register Lisp_Object elt_prefix;
                    909:      int (*elt_describer) ();
                    910:      int partial;
                    911: {
                    912:   Lisp_Object this;
                    913:   Lisp_Object dummy;
                    914:   Lisp_Object tem1, tem2;
                    915:   register int i, size = XVECTOR (vector)->size;
                    916:   int indent;
                    917:   Lisp_Object suppress;
                    918: 
                    919:   if (partial)
                    920:     suppress = intern ("suppress-keymap");
                    921: 
                    922:   for (i = 0; i < size; i++)
                    923:     {
                    924:       QUIT;
                    925:       tem1 = XVECTOR (vector)->contents[i];
                    926:       if (NULL (tem1)) continue;      
                    927:       if (XTYPE (tem1) == Lisp_Symbol && partial)
                    928:        {
                    929:          this = Fget (tem1, suppress);
                    930:          if (!NULL (this))
                    931:            continue;
                    932:        }
                    933: 
                    934:       indent = 0;
                    935: 
                    936:       if (!NULL (elt_prefix))
                    937:        {
                    938:          InsCStr (XSTRING (elt_prefix)->data, XSTRING (elt_prefix)->size);
                    939:          InsCStr (" ", 1);
                    940:          indent += XSTRING (elt_prefix)->size + 1;
                    941:        }
                    942:       XFASTINT (dummy) = i;
                    943:       this = Fsingle_key_description (dummy);
                    944:       InsCStr (XSTRING (this)->data, XSTRING (this)->size);
                    945:       indent += XSTRING (this)->size;
                    946: 
                    947:       while (i + 1 < size && (tem2 = XVECTOR (vector)->contents[i+1], EQ(tem2, tem1)))
                    948:        i++;
                    949: 
                    950:       if (i != XINT (dummy))
                    951:        {
                    952:          InsCStr (" .. ", 4);
                    953:          indent += 4;
                    954:          if (!NULL (elt_prefix))
                    955:            {
                    956:              InsCStr (XSTRING (elt_prefix)->data, XSTRING (elt_prefix)->size);
                    957:              InsCStr (" ", 1);
                    958:              indent += XSTRING (elt_prefix)->size + 1;
                    959:            }
                    960:          XFASTINT (dummy) = i;
                    961:          this = Fsingle_key_description (dummy);
                    962:          InsCStr (XSTRING (this)->data, XSTRING (this)->size);
                    963:          indent += XSTRING (this)->size;
                    964:        }
                    965: 
                    966:       InsCStr ("                    ", indent<16 ? 16-indent : 1);
                    967: 
                    968:       tem1 = XVECTOR (vector)->contents[i];
                    969:       (*elt_describer) (tem1);
                    970:       InsCStr ("\n", 1);
                    971:     }
                    972: }
                    973: 
                    974: /* Apropos */
                    975: Lisp_Object apropos_predicate;
                    976: Lisp_Object apropos_accumulate;
                    977: 
                    978: static
                    979: apropos_accum (symbol, string)
                    980:      Lisp_Object symbol, string;
                    981: {
                    982:   register Lisp_Object tem;
                    983: 
                    984:   tem = Fstring_match (string, Fsymbol_name (symbol), Qnil);
                    985:   if (!NULL (tem) && !NULL (apropos_predicate))
                    986:     tem = call1 (apropos_predicate, symbol);
                    987:   if (!NULL (tem))
                    988:     apropos_accumulate = Fcons (symbol, apropos_accumulate);
                    989: }
                    990: 
                    991: static Lisp_Object
                    992: apropos1 (list)
                    993:      register Lisp_Object list;
                    994: {
                    995:   struct buffer *old = bf_cur;
                    996:   register Lisp_Object symbol, col, tem;
                    997: 
                    998:   while (!NULL (list))
                    999:     {
                   1000:       QUIT;
                   1001: 
                   1002:       symbol = Fcar (list);
                   1003:       list = Fcdr (list);
                   1004: 
                   1005:       tem = where_is_in_buffer (symbol, bf_cur, 0);
                   1006:       tem = Fmapconcat (Qkey_description, tem, build_string (", "));
                   1007:       XFASTINT (col) = 30;
                   1008: 
                   1009:       SetBfp (XBUFFER (Vstandard_output));
                   1010:       Fprin1 (symbol, Qnil);
                   1011:       Findent_to (col, Qnil);
                   1012:       Fprinc (tem, Qnil);
                   1013:       Fterpri (Qnil);
                   1014:       tem = Ffboundp (symbol);
                   1015:       if (!NULL (tem))
                   1016:         tem = Fdocumentation (symbol);
                   1017:       if (XTYPE (tem) == Lisp_String)
                   1018:        insert_first_line ("  Function: ", tem);
                   1019:       tem = Fget (symbol, Qvariable_documentation);
                   1020:       if (XTYPE (tem) == Lisp_String)
                   1021:        insert_first_line ("  Variable: ", tem);
                   1022:       SetBfp (old);
                   1023:     }
                   1024:   return Qnil;
                   1025: }
                   1026: 
                   1027: static
                   1028: insert_first_line (prefix, str)
                   1029:      char *prefix;
                   1030:      Lisp_Object str;
                   1031: {
                   1032:   extern char *index ();
                   1033:   register unsigned char *p;
                   1034:   register unsigned char *p1;
                   1035:   register unsigned char *p2;
                   1036: 
                   1037:   InsStr (prefix);
                   1038: 
                   1039:  retry:
                   1040:   p = XSTRING (str)->data;
                   1041:   p1 = (unsigned char *) index (p, '\n');
                   1042: 
                   1043:   for (p2 = p; *p2 && p2 != p1; p2++)
                   1044:     if (p2[0] == '\\' && p2[1] == '[')
                   1045:       {
                   1046:        str = Fsubstitute_command_keys (str);
                   1047:        goto retry;
                   1048:       }
                   1049: 
                   1050:   InsCStr (p, p1 ? p1 - p : strlen (p));
                   1051:   InsCStr ("\n", 1);
                   1052: }
                   1053: 
                   1054: DEFUN ("apropos", Fapropos, Sapropos, 1, 3, "sApropos: ",
                   1055:   "Show all symbols whose names contain match for REGEXP.\n\
                   1056: If optional arg PRED is non-nil, (funcall PRED SYM) is done\n\
                   1057: for each symbol and a symbol is mentioned if that returns non-nil.\n\
                   1058: Returns list of symbols found; if third arg NOPRINT is non-nil,\n\
                   1059: does not display them, just returns the list.")
                   1060:   (string, pred, noprint)
                   1061:      Lisp_Object string, pred, noprint;
                   1062: {
                   1063:   struct gcpro gcpro1, gcpro2;
                   1064:   CHECK_STRING (string, 0);
                   1065:   apropos_predicate = pred;
                   1066:   GCPRO2 (apropos_predicate, apropos_accumulate);
                   1067:   apropos_accumulate = Qnil;
                   1068:   map_obarray (Vobarray, apropos_accum, string);
                   1069:   apropos_accumulate = Fsort (apropos_accumulate, Qstring_lessp);
                   1070:   if (NULL (noprint))
                   1071:     internal_with_output_to_temp_buffer ("*Help*", apropos1,
                   1072:                                         apropos_accumulate);
                   1073:   UNGCPRO;
                   1074:   return apropos_accumulate;
                   1075: }
                   1076: 
                   1077: DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command,
                   1078:   1, 1, "P",
                   1079:   "Read function name, then read its arguments and call it.")
                   1080:   (prefixarg)
                   1081:      Lisp_Object prefixarg;
                   1082: {
                   1083:   Lisp_Object function;
                   1084:   char buf[40];
                   1085: 
                   1086:   buf[0] = 0;
                   1087: 
                   1088:   if (EQ (prefixarg, Qminus))
                   1089:     strcpy (buf, "- ");
                   1090:   else if (LISTP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
                   1091:     strcpy (buf, "C-u ");
                   1092:   else if (LISTP (prefixarg) && XTYPE (XCONS (prefixarg)->car) == Lisp_Int)
                   1093:     sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
                   1094:   else if (XTYPE (prefixarg) == Lisp_Int)
                   1095:     sprintf (buf, "%d ", XINT (prefixarg));
                   1096: 
                   1097:   strcat (buf, "M-x ");
                   1098: 
                   1099:   function = Fcompleting_read (build_string (buf), Vobarray, Qcommandp, Qt, Qnil);
                   1100: 
                   1101:   Vprefix_arg = prefixarg;
                   1102:   return Fcommand_execute (Fintern (function, Vobarray), Qt);
                   1103: }
                   1104: 
                   1105: syms_of_keymap ()
                   1106: {
                   1107:   Lisp_Object tem;
                   1108: 
                   1109:   Qkeymap = intern ("keymap");
                   1110:   staticpro (&Qkeymap);
                   1111: 
                   1112: /* Initialize the keymaps standardly used.
                   1113:    Each one is the value of a Lisp variable, and is also
                   1114:    pointed to by a C variable */
                   1115: 
                   1116: #ifdef HAVE_X_WINDOWS
                   1117:   tem = Fmake_keymap ();
                   1118:   MouseMap = XVECTOR (tem);
                   1119:   Fset (intern ("mouse-map"), tem);
                   1120: #endif /* HAVE_X_WINDOWS */
                   1121: 
                   1122:   tem = Fmake_keymap ();
                   1123:   GlobalMap = XVECTOR (tem);
                   1124:   Fset (intern ("global-map"), tem);
                   1125: 
                   1126:   tem = Fmake_keymap ();
                   1127:   ESCmap = XVECTOR (tem);
                   1128:   Fset (intern ("esc-map"), tem);
                   1129:   Ffset (intern ("ESC-prefix"), tem);
                   1130: 
                   1131:   tem = Fmake_keymap ();
                   1132:   CtlXmap = XVECTOR (tem);
                   1133:   Fset (intern ("ctl-x-map"), tem);
                   1134:   Ffset (intern ("Control-X-prefix"), tem);
                   1135: 
                   1136:   DefLispVar ("minibuffer-local-map", &Vminibuffer_local_map,
                   1137:     "Default keymap to use when reading from the minibuffer.");
                   1138:   Vminibuffer_local_map = Fmake_sparse_keymap ();
                   1139: 
                   1140:   DefLispVar ("minibuffer-local-ns-map", &Vminibuffer_local_ns_map,
                   1141:     "The keymap used by the minibuf for local bindings when spaces are not\n\
                   1142: to be allowed in input string.");
                   1143:   Vminibuffer_local_ns_map = Fmake_sparse_keymap ();
                   1144: 
                   1145:   DefLispVar ("minibuffer-local-completion-map", &Vminibuffer_local_completion_map,
                   1146:     "Keymap to use when reading from the minibuffer with completion.");
                   1147:   Vminibuffer_local_completion_map = Fmake_sparse_keymap ();
                   1148: 
                   1149:   DefLispVar ("minibuffer-local-must-match-map", &Vminibuffer_local_must_match_map,
                   1150:     "Keymap to use when reading from the minibuffer with completion and\n\
                   1151: an exact match of one of the completions is required.");
                   1152:   Vminibuffer_local_must_match_map = Fmake_sparse_keymap ();
                   1153: 
                   1154:   CurrentGlobalMap = GlobalMap;
                   1155: 
                   1156:   Qsingle_key_description = intern ("single-key-description");
                   1157:   staticpro (&Qsingle_key_description);
                   1158: 
                   1159:   Qkey_description = intern ("key-description");
                   1160:   staticpro (&Qkey_description);
                   1161: 
                   1162:   Qkeymapp = intern ("keymapp");
                   1163:   staticpro (&Qkeymapp);
                   1164: 
                   1165:   defsubr (&Skeymapp);
                   1166:   defsubr (&Smake_keymap);
                   1167:   defsubr (&Smake_sparse_keymap);
                   1168:   defsubr (&Skey_binding);
                   1169:   defsubr (&Slocal_key_binding);
                   1170:   defsubr (&Sglobal_key_binding);
                   1171:   defsubr (&Sglobal_set_key);
                   1172:   defsubr (&Slocal_set_key);
                   1173:   defsubr (&Sdefine_key);
                   1174:   defsubr (&Slookup_key);
                   1175:   defsubr (&Sglobal_unset_key);
                   1176:   defsubr (&Slocal_unset_key);
                   1177:   defsubr (&Suse_global_map);
                   1178:   defsubr (&Suse_local_map);
                   1179:   defsubr (&Scurrent_local_map);
                   1180:   defsubr (&Saccessible_keymaps);
                   1181:   defsubr (&Skey_description);
                   1182:   defsubr (&Ssingle_key_description);
                   1183:   defsubr (&Stext_char_description);
                   1184:   defsubr (&Swhere_is_internal);
                   1185:   defsubr (&Swhere_is);
                   1186:   defsubr (&Sdescribe_bindings);
                   1187:   defsubr (&Sapropos);
                   1188:   defsubr (&Sexecute_extended_command);
                   1189: }
                   1190: 
                   1191: keys_of_keymap ()
                   1192: {
                   1193:   defkey (GlobalMap, 033, "ESC-prefix");
                   1194:   defkey (GlobalMap, Ctl('X'), "Control-X-prefix");
                   1195:   defkey (ESCmap, 'x', "execute-extended-command");
                   1196: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.