home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / cpm / emacs / emacssrc.lzh / mapkeys.c < prev    next >
C/C++ Source or Header  |  1992-03-11  |  13KB  |  354 lines

  1.  
  2. /**********************************************************/
  3. /*                                                        */
  4. /*  Implements CI-Vague-Input:                            */
  5. /*                                                        */
  6. /*  The task is to match up a command name from the       */
  7. /*  UECS with a user input. In the comparison, dashes     */
  8. /*  and case are ignored. Furthermore, the user can       */
  9. /*  input a partial string: "visi" returns                */
  10. /*                                                        */
  11. /*      SC-Visit-Cursor-Buffer                            */
  12. /*      SC-Visit-Cursor-File                              */
  13. /*      SC-Visit-File                                     */
  14. /*      UI-File-Selection-Visit-File                      */
  15. /*                                                        */
  16. /*  The above example also demonstrates the               */
  17. /*  significance of the dashes in the names in the        */
  18. /*  UECS list -- the portion of the name that follows     */
  19. /*  a dash is selectable!                                 */
  20. /*                                                        */
  21. /*  This means that this implementation of                */
  22. /*  CI-Vague-Input  also effectively includes             */
  23. /*  CI-Help-Apropos!                                      */
  24. /*                                                        */
  25. /*  The user's ability to enter a partial string          */
  26. /*  effectively implements a form of                      */
  27. /*  CI-Command-Completion!                                */
  28. /*                                                        */
  29. /**********************************************************/
  30.  
  31. #include "ostdio.h"
  32. #include "fcntl.h"
  33.  
  34. #define NSNLEN 50
  35. #define MAXnnoffs 8
  36.  
  37. struct ns
  38. {       int noff[MAXnnoffs];    /* noff[0] is offset of start of main portion. */
  39.         int nnoffs;
  40.         int nlen;
  41.         int nsnumber;
  42.         char nsname[NSNLEN];
  43.         char nsoname[NSNLEN];
  44. } nstab[200];
  45. int nsentries;
  46. struct ns * ns_matched;
  47.  
  48. char linebuf[256];
  49. char workbuf[256];
  50. int worklen;
  51.  
  52. char * UECSfile = "zmecmds.lst";
  53. char * outname =  "maptable.zme";
  54. int outfile;
  55.  
  56. main( argc, argv )
  57. char ** argv;
  58. {
  59.         if ( argc > 1 )
  60.         {       UECSfile = argv[1];
  61.         }
  62.         if ( argc > 2 )
  63.         {       outname = argv[2];
  64.         }
  65.         outfile = open( outname, O_CREAT|O_WRONLY|O_TRUNC );
  66.         if ( outfile < 0 )
  67.         {       fprintf( stderr, "could not open %d for output\n",
  68.                         outname );
  69.                 myexit ( 1 );
  70.         }
  71.  
  72.         nsload();
  73.         while ( 1 )
  74.         {       inget();
  75.                 if ( nscomp() == 1 ) dokey();
  76.         }
  77. }
  78.  
  79. nsload()
  80. {       FILE * inf;
  81.         int lnumber = 0;
  82.         int i, j;
  83.         char * cp, *qp;
  84.         int c;
  85.         struct ns * nsp;
  86.  
  87.         if ( ( inf = fopen( UECSfile, "r" )) == NULL )
  88.         {       fprintf( stderr, "open fails: %s\n", UECSfile );
  89.                 myexit ( 1 );
  90.         }
  91.         nsp = & nstab[0];
  92.  
  93.         while ( fgets( linebuf, 254, inf ) != NULL )
  94.         {       ++lnumber;
  95.                 if ( linebuf[0] < '0' || linebuf[0] > '9' ) continue;
  96.                 cp = linebuf;
  97.                 while ( c = *cp++ )
  98.                 {       if ( c == '\t' )
  99.                         {       goto foundtab;
  100.                         }
  101.                 }
  102.                 continue;
  103. foundtab:
  104.                 i = strlen( cp );
  105.                 while
  106.                 (       i > 0
  107.                 &&      (       ( c = cp[ --i ]) == '\n'
  108.                                 || c == '\r'
  109.                                 || c == ' '
  110.                                 || c == '\t'
  111.                         )
  112.                 )       cp[ i ] = 0;
  113.                 if ( i < 0 || i > ( NSNLEN - 1 ) ) continue;
  114.  
  115.                 for ( i = 0, qp = linebuf; *qp <= '9' && *qp >= '0'; ++qp )
  116.                 {       i *= 10;
  117.                         i += *qp - '0';
  118.                 }
  119.                 nsp->nsnumber = i;
  120.  
  121.                 strcpy( nsp->nsoname, cp );
  122.                 nsp->nnoffs = 0;
  123.                 for ( i = j = 0; nsp->nnoffs < MAXnnoffs && cp[ i ]; ++i )
  124.                 {       if (  cp[i] == '-' )
  125.                         {       nsp->noff[ nsp->nnoffs++ ] = j;
  126.                         }
  127.                         else ++j;
  128.                 }
  129.  
  130.                 for ( qp = nsp->nsname; *cp; ++cp )
  131.                 {       if ( *cp == '-' )  continue;
  132.                         c = *cp;
  133.                         if ( c >= 'A' && c <= 'Z' )
  134.                         {       c ^= ( 'a' ^ 'A' );             /* tolower */
  135.                         }
  136.                         *qp++ = c;
  137.                         *qp = 0;
  138.                 }
  139.                 nsp->nlen = strlen( nsp->nsname );
  140.                 ++nsp;
  141.                 ++nsentries;
  142.         }
  143.     printf( "Read %d lines\n\n", nsentries );
  144. }
  145.  
  146. inget()
  147. {       printf( "Enter a name: " );
  148.     linebuf[0] = 0;
  149.         if ( fgets( linebuf, 254, stdin ) == NULL 
  150.     || linebuf[0] == 26
  151.     || linebuf[0] == 0
  152.     || linebuf[0] == 4
  153.         )
  154.         {       printf( "\nreached EOF\n" );
  155.                 myexit ( 0 );
  156.         }
  157. }
  158. myexit( n )
  159. {       if ( outfile >= 0 ) close( outfile );
  160.         exit ( n );
  161. }
  162.  
  163. nscomp()
  164. {
  165.         int i, c, j;
  166.         char *  cp, *qp;
  167.         int wlen;
  168.         int nmatch;
  169.         struct ns * nsp;
  170.  
  171.         cp = linebuf;
  172.         nsp = &nstab[ nmatch = i = j = 0 ];
  173.  
  174.     if ( *cp == ( 'z' & 0x1f )) myexit ( 0 );
  175.     
  176.         while ( ( c = *cp++ ) >= '0' && c <= '9' )
  177.         {       /* Numeric. */
  178.                 j *= 10;
  179.                 j += c - '0';
  180.         }
  181.         if ( j )
  182.         {       /* Numeric. */
  183.                 for ( ; i < nsentries; ++nsp, ++i )
  184.                 {       if ( nsp->nsnumber != j ) continue;
  185.                         ++nmatch;
  186.                         ns_matched = nsp;
  187.                         printf( "%3d   %s\n", nsp->nsnumber,
  188.                                 nsp->nsoname );
  189.                 }
  190.                 goto outa_here;
  191.         }
  192.         --cp;
  193.         i = strlen( cp );
  194.         while
  195.         (       i > 0
  196.         &&      (       ( c = cp[ --i ]) == '\n'
  197.                         || c == '\r'
  198.                         || c == ' '
  199.                         || c == '\t'
  200.                 )
  201.         )       cp[ i ] = 0;
  202.         if ( i < 0 || i > ( NSNLEN - 1 ) )
  203.         {       printf( "bad input line\n" );
  204.                 myexit ( 0 );
  205.         }
  206.         /* i == 0 prints them all. */
  207.  
  208.         for ( qp = workbuf; *cp; ++cp )
  209.         {       if ( *cp == '-' )  continue;
  210.                 c = *cp;
  211.                 if ( c >= 'A' && c <= 'Z' )
  212.                 {       c ^= ( 'a' ^ 'A' );             /* tolower */
  213.                 }
  214.                 *qp++ = c;
  215.                 *qp = 0;
  216.         }
  217.         worklen = strlen( workbuf );
  218.         for ( i = 0; i < nsentries; ++nsp, ++i )
  219.         {
  220.                 wlen = nsp->nlen;
  221.                 if ( worklen > wlen )
  222.                 {       /* if the string that the user entered is longer
  223.                         ** than the string in the table, this is a
  224.                         ** mismatch!
  225.                         */
  226.                         continue;
  227.                 }
  228.  
  229.                 if ( worklen < wlen ) wlen = worklen;
  230.                 if ( ! strncmp( workbuf, nsp->nsname, wlen ))
  231.                 {       printf( "%3d   %s\n", nsp->nsnumber,
  232.                                 nsp->nsoname );
  233.                         ns_matched = nsp;
  234.                         retcon( ++nmatch );
  235.                         continue;
  236.                 }
  237.  
  238.                 for ( j = 0; j < nsp->nnoffs; ++j )
  239.                 {       /* try pieces of the input name. */
  240.                         wlen = nsp->nlen - nsp->noff[j];
  241.                         if ( worklen > wlen ) break;
  242.                         if ( worklen < wlen ) wlen = worklen;
  243.                         if ( ! strncmp( workbuf,
  244.                                 &nsp->nsname[ nsp->noff[j] ], wlen ))
  245.                         {       printf( "%3d   %s\n", nsp->nsnumber,
  246.                                         nsp->nsoname );
  247.                                 ns_matched = nsp;
  248.                                 retcon( ++nmatch );
  249.                                 break;
  250.                         }
  251.                 }
  252.         }
  253. outa_here:
  254.         printf( "===== %d matches\n", nmatch );
  255.         return nmatch;
  256. }
  257. retcon( n )
  258. {       if ( n % 23 ) return;
  259.         printf( "[MORE]" );
  260.         while ( ( n = getchar()) != '\n' && n != EOF );
  261. }
  262. struct
  263. {       int UECSout;
  264.         int KEYout;
  265. } out;
  266.  
  267. dokey()
  268. {       /* ns_matched is set to the nstab entry we need. */
  269.         int result, i, c, flags, state;
  270. #define META  0x200
  271. #define CTLX  0x400
  272. #define MAGIC 0x100
  273.  
  274. again:
  275.         i = -1;
  276.         flags = state = 0;
  277.         printf( "Enter a keystroke sequence: " );
  278.         while ( ( c = getchar()) != EOF && c != '\n' )
  279.         {       if ( state & 4 ) continue;
  280.                 switch ( c )
  281.                 {       case '\r':
  282.                         case ' ':
  283.                                 continue;
  284.                         case '^':
  285.                                 if ( ! ( state & 1 ))
  286.                                 {       state |= 1;
  287.                                         continue;
  288.                                 }
  289. ctlchar:                i = c & 0x1f;
  290. ctldel:                         state &= ~1;
  291.                                 if ( ! ( state & 2 ))
  292.                                 {       /* first character */
  293.                                         if ( i == ( 'x' & 0x1f ))
  294.                                         {       state |= 2;
  295.                                                 flags |= CTLX;
  296.                                                 continue;
  297.                                         }
  298.                                         if ( i == 0x1b )
  299.                                         {       state |= 2;
  300.                                                 flags |= META;
  301.                                                 continue;
  302.                                         }
  303.                                         if ( i == 1 )
  304.                                         {       state |= 2;
  305.                                                 flags |= MAGIC;
  306.                                                 continue;
  307.                                         }
  308.                                         state |= 4;
  309.                                         continue;
  310.                                 }       /* else second character: */
  311.                                 state |= 4;
  312.                                 continue;
  313.                         case '?':
  314.                                 if ( state & 1 )
  315.                                 {       i = 0x7f;
  316.                                         goto ctldel;
  317.                                 }
  318.                         default:
  319.                                 i = c;
  320.                                 if ( c < 0x20 || c > 0x7f ) continue;
  321.                                 if ( state & 1 ) goto ctlchar;
  322.                                 if ( ! ( state & 2 )) flags = -1;
  323.                                 state |= 4;
  324.                                 continue;
  325.                 }
  326.         }
  327.         switch ( flags )
  328.         {       case META:
  329.                 case CTLX:
  330.                         break;
  331.                 case 0:
  332.                         if ( ! ( i >= 0x20 && i <= 0x7f )) break;
  333.                         goto badseq;
  334.                 case MAGIC:
  335.                         if ( i >= 0x20 && i <= 0x7f ) break;
  336.                 default:
  337. badseq:         printf( "Please try again\n" );
  338.                         goto again;
  339.         }
  340.         if ( i == -1 )
  341.         {       printf( "Okay, we'll skip this one.\n" );
  342.                 return;
  343.         }
  344.  
  345.         out.UECSout = ns_matched->nsnumber;
  346.         out.KEYout = i | flags;
  347.         if ( write( outfile, &out, sizeof( out )) != sizeof( out ))
  348.         {       fprintf( stderr, "write error\n" );
  349.                 myexit( 1 );
  350.         }
  351.         printf( "The internal code 0x%x has been mapped to %d   %s\n",
  352.                 i | flags, ns_matched->nsnumber, ns_matched->nsoname );
  353. }
  354.