1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.xmap.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * ed.xmap.c: This module contains the procedures for maintaining
   4:  *	      the extended-key map.
   5:  *
   6:  * 	      An extended-key (Xkey) is a sequence of keystrokes
   7:  *	      introduced with an sequence introducer and consisting
   8:  *	      of an arbitrary number of characters.  This module maintains
   9:  *	      a map (the Xmap) to convert these extended-key sequences
  10:  * 	      into input strings or editor functions. It contains the
  11:  *	      following externally visible functions.
  12:  *
  13:  *		int GetXkey(ch,code);
  14:  *		Char *ch;
  15:  *		Char **code;
  16:  *
  17:  *	      Looks up *ch in map and then reads characters until a
  18:  *	      complete match is found or a mismatch occurs.  Returns 1
  19:  *	      for command and 0 for a string. Returns NULL in code for
  20:  *	      no match and 0 as value.  The last character read is returned
  21:  *	      in *ch.
  22:  *
  23:  *		void AddXkey(Xkey, code);
  24:  *		Char *Xkey;
  25:  *		Char * code;
  26:  *
  27:  *		void AddXKeyCmd(Xkey, CmdCode);
  28:  *		Char *Xkey;
  29:  *		Char CmdCode;
  30:  *
  31:  *	      Adds Xkey to the Xmap and associates the code with it.  If
  32:  *	      Xkey is already is in Xmap, the new code is applied to the
  33:  *	      existing Xkey.
  34:  *
  35:  *	        int DeleteXkey(Xkey);
  36:  *	        Char *Xkey;
  37:  *
  38:  *	      Delete the Xkey and all longer Xkeys staring with Xkey, if
  39:  *	      they exists.
  40:  *
  41:  *	      Warning:
  42:  *		If Xkey is a substring of some other Xkeys, then the longer
  43:  *		Xkeys are lost!!  That is, if the Xkeys "abcd" and "abcef"
  44:  *		are in Xmap, adding the key "abc" will cause the first two
  45:  *		definitions to be lost.
  46:  *
  47:  *		void ResetXmap();
  48:  *
  49:  *	      Removes all entries from Xmap and resets the defaults.
  50:  *
  51:  *		void PrintXkey(Xkey);
  52:  *		Char *Xkey;
  53:  *
  54:  *	      Prints all extended keys prefixed by Xkey and their associated
  55:  *	      commands.
  56:  *
  57:  *	      Restrictions:
  58:  *	      -------------
  59:  *	        1) It is not possible to have one Xkey that is a
  60:  *		   substring of another.
  61:  */
  62: /*-
  63:  * Copyright (c) 1980, 1991 The Regents of the University of California.
  64:  * All rights reserved.
  65:  *
  66:  * Redistribution and use in source and binary forms, with or without
  67:  * modification, are permitted provided that the following conditions
  68:  * are met:
  69:  * 1. Redistributions of source code must retain the above copyright
  70:  *    notice, this list of conditions and the following disclaimer.
  71:  * 2. Redistributions in binary form must reproduce the above copyright
  72:  *    notice, this list of conditions and the following disclaimer in the
  73:  *    documentation and/or other materials provided with the distribution.
  74:  * 3. All advertising materials mentioning features or use of this software
  75:  *    must display the following acknowledgement:
  76:  *	This product includes software developed by the University of
  77:  *	California, Berkeley and its contributors.
  78:  * 4. Neither the name of the University nor the names of its contributors
  79:  *    may be used to endorse or promote products derived from this software
  80:  *    without specific prior written permission.
  81:  *
  82:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  83:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  84:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  85:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  86:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  87:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  88:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  89:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  90:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  91:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  92:  * SUCH DAMAGE.
  93:  */
  94: #include "config.h"
  95: #if !defined(lint) && !defined(pdp11)
  96: static char *rcsid()
  97:     { return "$Id: ed.xmap.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  98: #endif
  99: 
 100: #include "sh.h"
 101: #include "ed.h"
 102: #include "ed.defns.h"
 103: 
 104: #ifndef NULL
 105: #define NULL 0
 106: #endif
 107: 
 108: /* Internal Data types and declarations */
 109: 
 110: /* The Nodes of the Xmap.  The Xmap is a linked list of these node
 111:  * elements
 112:  */
 113: typedef struct Xmapnode {
 114:     Char    ch;         /* single character of Xkey */
 115:     Char   *code;       /* command code or pointer to string, if this
 116: 				 * is a leaf */
 117:     struct Xmapnode *next;  /* ptr to next char of this Xkey */
 118:     struct Xmapnode *sibling;   /* ptr to another Xkey with same prefix */
 119: }       XmapNode;
 120: 
 121: static XmapNode *Xmap = NULL;   /* the current Xmap */
 122: 
 123: static Char CurCode;
 124: static XmapNode CurCmd = {0, &CurCode, NULL, NULL};
 125: 
 126: /* Some declarations of procedures */
 127: static  int          TraverseMap    __P((XmapNode *, Char *, Char **));
 128: static  int          TryNode    __P((XmapNode *, Char *, Char *, int));
 129: static  XmapNode    *GetFreeNode    __P((int));
 130: static  void         PutFreeNode    __P((XmapNode *));
 131: static  int      TryDeleteNode  __P((XmapNode **, Char *));
 132: 
 133: 
 134: /* ResetXmap():
 135:  *	Takes all nodes on Xmap and puts them on free list.  Then
 136:  *	initializes Xmap with arrow keys
 137:  */
 138: void
 139: ResetXmap(vi)
 140:     int     vi;
 141: {
 142:     static Char strA[] = {033, '[', 'A', '\0'};
 143:     static Char strB[] = {033, '[', 'B', '\0'};
 144:     static Char strC[] = {033, '[', 'C', '\0'};
 145:     static Char strD[] = {033, '[', 'D', '\0'};
 146:     static Char stOA[] = {033, 'O', 'A', '\0'};
 147:     static Char stOB[] = {033, 'O', 'B', '\0'};
 148:     static Char stOC[] = {033, 'O', 'C', '\0'};
 149:     static Char stOD[] = {033, 'O', 'D', '\0'};
 150: 
 151:     PutFreeNode(Xmap);
 152:     Xmap = NULL;
 153:     AddXKeyCmd(strA, F_UP_HIST);
 154:     AddXKeyCmd(strB, F_DOWN_HIST);
 155:     AddXKeyCmd(strC, F_CHARFWD);
 156:     AddXKeyCmd(strD, F_CHARBACK);
 157:     AddXKeyCmd(stOA, F_UP_HIST);
 158:     AddXKeyCmd(stOB, F_DOWN_HIST);
 159:     AddXKeyCmd(stOC, F_CHARFWD);
 160:     AddXKeyCmd(stOD, F_CHARBACK);
 161:     if (vi) {
 162:     AddXKeyCmd(&strA[1], F_UP_HIST);
 163:     AddXKeyCmd(&strB[1], F_DOWN_HIST);
 164:     AddXKeyCmd(&strC[1], F_CHARFWD);
 165:     AddXKeyCmd(&strD[1], F_CHARBACK);
 166:     AddXKeyCmd(&stOA[1], F_UP_HIST);
 167:     AddXKeyCmd(&stOB[1], F_DOWN_HIST);
 168:     AddXKeyCmd(&stOC[1], F_CHARFWD);
 169:     AddXKeyCmd(&stOD[1], F_CHARBACK);
 170:     }
 171:     return;
 172: }
 173: 
 174: 
 175: /* GetXkey():
 176:  *	Calls the recursive function with entry point Xmap
 177:  */
 178: int
 179: GetXkey(ch, code)
 180:     Char   *ch;
 181:     Char  **code;
 182: {
 183:     return (TraverseMap(Xmap, ch, code));
 184: }
 185: 
 186: /* TraverseMap():
 187:  *	recursively traverses node in tree until match or mismatch is
 188:  * 	found.  May read in more characters.
 189:  */
 190: static int
 191: TraverseMap(ptr, ch, code)
 192:     XmapNode *ptr;
 193:     Char   *ch;
 194:     Char  **code;
 195: {
 196:     Char    tch;
 197: 
 198:     if (ptr->ch == *ch) {
 199:     /* match found */
 200:     if (ptr->next) {
 201:         if (ptr->next != &CurCmd) {
 202:         /* Xkey not complete so get next char */
 203:         if (G_N_Char(&tch) != 1) {  /* if EOF or error */
 204:             *ch = 0;
 205:             CurCmd.code[0] = F_SEND_EOF;
 206:             *code = CurCmd.code;
 207:             return 1;   /* PWP: Pretend we just read an end-of-file */
 208:         }
 209:         *ch = tch;
 210:         return (TraverseMap(ptr->next, ch, code));
 211:         }
 212:         else {
 213:         CurCmd.code[0] = (Char) ptr->code;
 214:         *code = CurCmd.code;
 215:         return 1;
 216:         }
 217:     }
 218:     else {
 219:         /* next is null so this is leaf node and a string */
 220:         *ch = 0;
 221:         *code = ptr->code;
 222:         return 0;
 223:     }
 224:     }
 225:     else {
 226:     /* no match found here */
 227:     if (ptr->sibling) {
 228:         /* try next sibling */
 229:         return (TraverseMap(ptr->sibling, ch, code));
 230:     }
 231:     else {
 232:         /* no next sibling -- mismatch */
 233:         *code = NULL;
 234:         return 0;
 235:     }
 236:     }
 237: }
 238: 
 239: void
 240: AddXkey(Xkey, code)
 241:     Char   *Xkey;
 242:     Char   *code;
 243: {
 244:     if (Xkey[0] == '\0') {
 245:     xprintf("AddXkey: Null extended-key not allowed.\n");
 246:     return;
 247:     }
 248: 
 249:     if (Xmap == NULL)
 250:     /* tree is initially empty.  Set up new node to match Xkey[0] */
 251:     Xmap = GetFreeNode(Xkey[0]);    /* it is properly initialized */
 252: 
 253:     /* Now recurse through Xmap */
 254:     (void) TryNode(Xmap, Xkey, code, 1);    /* string */
 255:     return;
 256: }
 257: 
 258: void
 259: AddXKeyCmd(Xkey, CmdCode)
 260:     Char   *Xkey;
 261:     int    CmdCode;
 262: {
 263:     /* Gould does not like casts... */
 264:     unsigned int comp_r_bug;
 265: 
 266:     if (Xkey[0] == '\0') {
 267:     xprintf("AddXKeyCmd: Null extended-key not allowed.\n");
 268:     return;
 269:     }
 270:     if (CmdCode == F_XKEY) {
 271:     xprintf("AddXKeyCmd: sequence-lead-in command not allowed\n");
 272:     return;
 273:     }
 274: 
 275:     if (Xmap == NULL)
 276:     /* tree is initially empty.  Set up new node to match Xkey[0] */
 277:     Xmap = GetFreeNode(Xkey[0]);    /* it is properly initialized */
 278: 
 279:     /* Now recurse through Xmap */
 280:     comp_r_bug = (unsigned int) CmdCode;
 281:     (void) TryNode(Xmap, Xkey, (Char *) comp_r_bug, 0); /* command */
 282:     return;
 283: }
 284: 
 285: 
 286: static int
 287: TryNode(ptr, string, code, IsString)
 288:     XmapNode *ptr;
 289:     Char   *string;
 290:     Char   *code;
 291:     int     IsString;
 292: {
 293:     /*
 294:      * Find a node that matches *string or allocate a new one
 295:      */
 296:     if (ptr->ch != *string) {
 297:     XmapNode *xm;
 298: 
 299:     for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
 300:         if (xm->sibling->ch == *string)
 301:         break;
 302:     if (xm->sibling == NULL)
 303:         xm->sibling = GetFreeNode(*string); /* setup new node */
 304:     ptr = xm->sibling;
 305:     }
 306: 
 307:     if (*++string == '\0') {
 308:     /* we're there */
 309:     if (ptr->next != NULL && ptr->next != &CurCmd) {
 310:         PutFreeNode(ptr->next); /* lose longer Xkeys with this prefix */
 311:         ptr->next = NULL;
 312:     }
 313:     if (ptr->next == NULL && ptr->code)
 314:         xfree((ptr_t) ptr->code);
 315:     if (IsString) {
 316:         ptr->next = NULL;
 317:         ptr->code = Strsave(code);
 318:     }
 319:     else {
 320:         ptr->next = &CurCmd;
 321:         ptr->code = code;
 322:     }
 323:     }
 324:     else {
 325:     /* still more chars to go */
 326:     /*
 327: 	 * christos: We need to allocate a new XmapNode also if the next
 328: 	 * XmapNode is the CurCmd, cause the previous XmapNode definition was
 329: 	 * only one char long!
 330: 	 */
 331:     if (ptr->next == NULL || ptr->next == &CurCmd)
 332:         ptr->next = GetFreeNode(*string);   /* setup new node */
 333:     (void) TryNode(ptr->next, string, code, IsString);
 334:     }
 335:     return (0);
 336: }
 337: 
 338: void
 339: ClearXkey(map, in)
 340:     KEYCMD *map;
 341:     Char   *in;
 342: {
 343:     if ((map[(unsigned char) *in] == F_XKEY) &&
 344:     ((map == CcKeyMap && CcAltMap[(unsigned char) *in] != F_XKEY) ||
 345:      (map == CcAltMap && CcKeyMap[(unsigned char) *in] != F_XKEY)))
 346:     (void) DeleteXkey(in);
 347: }
 348: 
 349: int
 350: DeleteXkey(Xkey)
 351:     Char   *Xkey;
 352: {
 353:     if (Xkey[0] == '\0') {
 354:     xprintf("DeleteXkey: Null extended-key not allowed.\n");
 355:     return (-1);
 356:     }
 357: 
 358:     if (Xmap == NULL)
 359:     return (0);
 360: 
 361:     (void) TryDeleteNode(&Xmap, Xkey);
 362:     return (0);
 363: }
 364: 
 365: static int
 366: TryDeleteNode(inptr, string)
 367:     XmapNode **inptr;
 368:     Char   *string;
 369: {
 370:     XmapNode *ptr;
 371:     XmapNode *prev_ptr = NULL;
 372: 
 373:     ptr = *inptr;
 374:     /*
 375:      * Find a node that matches *string or allocate a new one
 376:      */
 377:     if (ptr->ch != *string) {
 378:     XmapNode *xm;
 379: 
 380:     for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
 381:         if (xm->sibling->ch == *string)
 382:         break;
 383:     if (xm->sibling == NULL)
 384:         return (0);
 385:     prev_ptr = xm;
 386:     ptr = xm->sibling;
 387:     }
 388: 
 389:     if (*++string == '\0') {
 390:     /* we're there */
 391:     if (prev_ptr == NULL)
 392:         *inptr = ptr->sibling;
 393:     else
 394:         prev_ptr->sibling = ptr->sibling;
 395:     ptr->sibling = NULL;
 396:     PutFreeNode(ptr);
 397:     return (1);
 398:     }
 399:     else if (ptr->next != NULL && TryDeleteNode(&ptr->next, string) == 1) {
 400:     if (ptr->next != NULL)
 401:         return (0);
 402:     if (prev_ptr == NULL)
 403:         *inptr = ptr->sibling;
 404:     else
 405:         prev_ptr->sibling = ptr->sibling;
 406:     ptr->sibling = NULL;
 407:     PutFreeNode(ptr);
 408:     return (1);
 409:     }
 410:     else {
 411:     return (0);
 412:     }
 413: }
 414: 
 415: 
 416: 
 417: 
 418: 
 419: /* PutFreeNode():
 420:  *	Puts a tree of nodes onto free list using free(3).
 421:  */
 422: static void
 423: PutFreeNode(ptr)
 424:     XmapNode *ptr;
 425: {
 426:     if (ptr == NULL)
 427:     return;
 428: 
 429:     if (ptr->next && ptr->next != &CurCmd)
 430:     PutFreeNode(ptr->next);
 431:     PutFreeNode(ptr->sibling);
 432:     if (ptr->next == NULL && ptr->code)
 433:     xfree((ptr_t) ptr->code);
 434:     xfree((ptr_t) ptr);
 435: }
 436: 
 437: 
 438: /* GetFreeNode():
 439:  *	Returns pointer to an XmapNode for ch.
 440:  */
 441: static XmapNode *
 442: GetFreeNode(ch)
 443:     int    ch;
 444: {
 445:     XmapNode *ptr;
 446: 
 447:     ptr = (XmapNode *) xmalloc((size_t) sizeof(XmapNode));
 448:     ptr->ch = ch;
 449:     ptr->code = NULL;
 450:     ptr->next = NULL;
 451:     ptr->sibling = NULL;
 452:     return (ptr);
 453: }
 454: 
 455: /* Now The Print Routine */
 456: #define maxXkey 100     /* max length of a Xkey for print putposes */
 457: static Char printbuf[maxXkey];  /* buffer for printing */
 458: 
 459: static int Lookup();
 460: static int Enumerate();
 461: static int printOne();
 462: static int u_p_ch();
 463: extern unsigned char *u_p_string();
 464: 
 465: /* PrintXKey():
 466:  *	Print the binding associated with Xkey key.
 467:  *	Print entire Xmap if null
 468:  */
 469: void
 470: PrintXkey(key)
 471:     Char   *key;
 472: {
 473:     /* do nothing if Xmap is empty and null key specified */
 474:     if (Xmap == NULL && *key == 0)
 475:     return;
 476: 
 477:     printbuf[0] = '"';
 478:     if (Lookup(key, Xmap, 1) <= -1)
 479:     /* key is not bound */
 480:     xprintf("Unbound extended key \"%s\"\n", short2str(key));
 481:     return;
 482: }
 483: 
 484: /* Lookup():
 485:  *	look for the string starting at node ptr.
 486:  *	Print if last node
 487:  */
 488: static int
 489: Lookup(string, ptr, cnt)
 490:     int     cnt;
 491:     Char   *string;
 492:     XmapNode *ptr;
 493: {
 494:     int     ncnt;
 495: 
 496:     if (ptr == NULL)
 497:     return (-1);        /* cannot have null ptr */
 498: 
 499:     if (*string == 0) {
 500:     /* no more chars in string.  Enumerate from here. */
 501:     (void) Enumerate(ptr, cnt);
 502:     return (0);
 503:     }
 504:     else {
 505:     /* If match put this char into printbuf.  Recurse */
 506:     if (ptr->ch == *string) {
 507:         /* match found */
 508:         ncnt = u_p_ch(cnt, ptr->ch);
 509:         if (ptr->next && ptr->next != &CurCmd)
 510:         /* not yet at leaf */
 511:         return (Lookup(string + 1, ptr->next, ncnt + 1));
 512:         else {
 513:         /* next node is null  or &CurCmd so key should be complete */
 514:         if (string[1] == 0) {
 515:             printbuf[ncnt + 1] = '"';
 516:             printbuf[ncnt + 2] = '\0';
 517:             (void) printOne(printbuf, ptr->code, ptr->next == NULL);
 518:             return (0);
 519:         }
 520:         else
 521:             return (-1);/* mismatch -- string still has chars */
 522:         }
 523:     }
 524:     else {
 525:         /* no match found try sibling */
 526:         if (ptr->sibling)
 527:         return (Lookup(string, ptr->sibling, cnt));
 528:         else
 529:         return (-1);
 530:     }
 531:     }
 532: }
 533: 
 534: static int
 535: Enumerate(ptr, cnt)
 536:     int     cnt;
 537:     XmapNode *ptr;
 538: {
 539:     int     ncnt;
 540: 
 541:     if (cnt >= maxXkey - 5) {   /* buffer too small */
 542:     printbuf[++cnt] = '"';
 543:     printbuf[++cnt] = '\0';
 544:     xprintf("Some extended keys too long for internal print buffer");
 545:     xprintf(" \"%s...\"\n", short2str(printbuf));
 546:     return (0);
 547:     }
 548: 
 549:     if (ptr == NULL) {
 550: #ifdef DEBUG_EDIT
 551:     xprintf("Enumerate: BUG!! Null ptr passed\n!");
 552: #endif
 553:     return (-1);
 554:     }
 555: 
 556:     ncnt = u_p_ch(cnt, ptr->ch);    /* put this char at end of string */
 557:     if (ptr->next == NULL || ptr->next == &CurCmd) {
 558:     /* print this Xkey and function */
 559:     printbuf[ncnt + 1] = '"';
 560:     printbuf[ncnt + 2] = '\0';
 561:     (void) printOne(printbuf, ptr->code, ptr->next == NULL);
 562:     }
 563:     else
 564:     (void) Enumerate(ptr->next, ncnt + 1);
 565: 
 566:     /* go to sibling if there is one */
 567:     if (ptr->sibling)
 568:     (void) Enumerate(ptr->sibling, cnt);
 569:     return (0);
 570: }
 571: 
 572: 
 573: /* PrintOne():
 574:  *	Print the specified key and its associated
 575:  *	function specified by code
 576:  */
 577: static int
 578: printOne(key, code, prstring)
 579:     Char   *key;
 580:     Char   *code;
 581:     int     prstring;
 582: {
 583:     struct KeyFuncs *fp;
 584:     unsigned char unparsbuf[200];
 585:     static char *fmt = "%-15s->  %s\n";
 586: 
 587:     if (code) {
 588:     if (prstring)
 589:         xprintf(fmt, short2str(key), u_p_string(code, unparsbuf));
 590:     else {
 591:         for (fp = FuncNames; fp->name; fp++) {
 592:         if ((int) code == fp->func)
 593:             xprintf(fmt, short2str(key), fp->name);
 594:         }
 595:     }
 596:     }
 597:     else
 598:     xprintf(fmt, short2str(key), "no input");
 599:     return (0);
 600: }
 601: 
 602: static int
 603: u_p_ch(cnt, ch)
 604:     int     cnt;
 605:     Char    ch;
 606: {
 607:     if (ch == 0) {
 608:     printbuf[cnt++] = '^';
 609:     printbuf[cnt] = '@';
 610:     return cnt;
 611:     }
 612: 
 613:     if (Iscntrl(ch)) {
 614:     printbuf[cnt++] = '^';
 615:     if (ch == '\177')
 616:         printbuf[cnt] = '?';
 617:     else
 618:         printbuf[cnt] = ch | 0100;
 619:     }
 620:     else if (ch == '^') {
 621:     printbuf[cnt++] = '\\';
 622:     printbuf[cnt] = '^';
 623:     }
 624:     else if (ch == '\\') {
 625:     printbuf[cnt++] = '\\';
 626:     printbuf[cnt] = '\\';
 627:     }
 628:     else if (ch == ' ' || (Isprint(ch) && !Isspace(ch))) {
 629:     printbuf[cnt] = ch;
 630:     }
 631:     else {
 632:     printbuf[cnt++] = '\\';
 633:     printbuf[cnt++] = ((ch >> 6) & 7) + '0';
 634:     printbuf[cnt++] = ((ch >> 3) & 7) + '0';
 635:     printbuf[cnt] = (ch & 7) + '0';
 636:     }
 637:     return cnt;
 638: }

Defined functions

AddXkey defined in line 239; used 1 times
ClearXkey defined in line 338; used 2 times
DeleteXkey defined in line 349; used 4 times
Enumerate defined in line 534; used 4 times
GetFreeNode defined in line 441; used 4 times
GetXkey defined in line 178; used 1 times
Lookup defined in line 488; used 4 times
PrintXkey defined in line 469; used 4 times
PutFreeNode defined in line 422; used 6 times
ResetXmap defined in line 138; used 2 times
TraverseMap defined in line 190; used 3 times
TryDeleteNode defined in line 365; used 2 times
TryNode defined in line 286; used 3 times
printOne defined in line 577; used 3 times
rcsid defined in line 96; never used
u_p_ch defined in line 602; used 3 times

Defined variables

CurCmd defined in line 124; used 11 times
CurCode defined in line 123; used 1 times
Xmap defined in line 121; used 13 times
printbuf defined in line 457; used 24 times

Defined struct's

Xmapnode defined in line 113; used 4 times

Defined typedef's

XmapNode defined in line 119; used 21 times

Defined macros

NULL defined in line 105; used 36 times
maxXkey defined in line 456; used 2 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3066
Valid CSS Valid XHTML 1.0 Strict