home *** CD-ROM | disk | FTP | other *** search
-
- /**********************************************************/
- /* */
- /* Implements CI-Vague-Input: */
- /* */
- /* The task is to match up a command name from the */
- /* UECS with a user input. In the comparison, dashes */
- /* and case are ignored. Furthermore, the user can */
- /* input a partial string: "visi" returns */
- /* */
- /* SC-Visit-Cursor-Buffer */
- /* SC-Visit-Cursor-File */
- /* SC-Visit-File */
- /* UI-File-Selection-Visit-File */
- /* */
- /* The above example also demonstrates the */
- /* significance of the dashes in the names in the */
- /* UECS list -- the portion of the name that follows */
- /* a dash is selectable! */
- /* */
- /* This means that this implementation of */
- /* CI-Vague-Input also effectively includes */
- /* CI-Help-Apropos! */
- /* */
- /* The user's ability to enter a partial string */
- /* effectively implements a form of */
- /* CI-Command-Completion! */
- /* */
- /**********************************************************/
-
- #include "ostdio.h"
- #include "fcntl.h"
-
- #define NSNLEN 50
- #define MAXnnoffs 8
-
- struct ns
- { int noff[MAXnnoffs]; /* noff[0] is offset of start of main portion. */
- int nnoffs;
- int nlen;
- int nsnumber;
- char nsname[NSNLEN];
- char nsoname[NSNLEN];
- } nstab[200];
- int nsentries;
- struct ns * ns_matched;
-
- char linebuf[256];
- char workbuf[256];
- int worklen;
-
- char * UECSfile = "zmecmds.lst";
- char * outname = "maptable.zme";
- int outfile;
-
- main( argc, argv )
- char ** argv;
- {
- if ( argc > 1 )
- { UECSfile = argv[1];
- }
- if ( argc > 2 )
- { outname = argv[2];
- }
- outfile = open( outname, O_CREAT|O_WRONLY|O_TRUNC );
- if ( outfile < 0 )
- { fprintf( stderr, "could not open %d for output\n",
- outname );
- myexit ( 1 );
- }
-
- nsload();
- while ( 1 )
- { inget();
- if ( nscomp() == 1 ) dokey();
- }
- }
-
- nsload()
- { FILE * inf;
- int lnumber = 0;
- int i, j;
- char * cp, *qp;
- int c;
- struct ns * nsp;
-
- if ( ( inf = fopen( UECSfile, "r" )) == NULL )
- { fprintf( stderr, "open fails: %s\n", UECSfile );
- myexit ( 1 );
- }
- nsp = & nstab[0];
-
- while ( fgets( linebuf, 254, inf ) != NULL )
- { ++lnumber;
- if ( linebuf[0] < '0' || linebuf[0] > '9' ) continue;
- cp = linebuf;
- while ( c = *cp++ )
- { if ( c == '\t' )
- { goto foundtab;
- }
- }
- continue;
- foundtab:
- i = strlen( cp );
- while
- ( i > 0
- && ( ( c = cp[ --i ]) == '\n'
- || c == '\r'
- || c == ' '
- || c == '\t'
- )
- ) cp[ i ] = 0;
- if ( i < 0 || i > ( NSNLEN - 1 ) ) continue;
-
- for ( i = 0, qp = linebuf; *qp <= '9' && *qp >= '0'; ++qp )
- { i *= 10;
- i += *qp - '0';
- }
- nsp->nsnumber = i;
-
- strcpy( nsp->nsoname, cp );
- nsp->nnoffs = 0;
- for ( i = j = 0; nsp->nnoffs < MAXnnoffs && cp[ i ]; ++i )
- { if ( cp[i] == '-' )
- { nsp->noff[ nsp->nnoffs++ ] = j;
- }
- else ++j;
- }
-
- for ( qp = nsp->nsname; *cp; ++cp )
- { if ( *cp == '-' ) continue;
- c = *cp;
- if ( c >= 'A' && c <= 'Z' )
- { c ^= ( 'a' ^ 'A' ); /* tolower */
- }
- *qp++ = c;
- *qp = 0;
- }
- nsp->nlen = strlen( nsp->nsname );
- ++nsp;
- ++nsentries;
- }
- printf( "Read %d lines\n\n", nsentries );
- }
-
- inget()
- { printf( "Enter a name: " );
- linebuf[0] = 0;
- if ( fgets( linebuf, 254, stdin ) == NULL
- || linebuf[0] == 26
- || linebuf[0] == 0
- || linebuf[0] == 4
- )
- { printf( "\nreached EOF\n" );
- myexit ( 0 );
- }
- }
- myexit( n )
- { if ( outfile >= 0 ) close( outfile );
- exit ( n );
- }
-
- nscomp()
- {
- int i, c, j;
- char * cp, *qp;
- int wlen;
- int nmatch;
- struct ns * nsp;
-
- cp = linebuf;
- nsp = &nstab[ nmatch = i = j = 0 ];
-
- if ( *cp == ( 'z' & 0x1f )) myexit ( 0 );
-
- while ( ( c = *cp++ ) >= '0' && c <= '9' )
- { /* Numeric. */
- j *= 10;
- j += c - '0';
- }
- if ( j )
- { /* Numeric. */
- for ( ; i < nsentries; ++nsp, ++i )
- { if ( nsp->nsnumber != j ) continue;
- ++nmatch;
- ns_matched = nsp;
- printf( "%3d %s\n", nsp->nsnumber,
- nsp->nsoname );
- }
- goto outa_here;
- }
- --cp;
- i = strlen( cp );
- while
- ( i > 0
- && ( ( c = cp[ --i ]) == '\n'
- || c == '\r'
- || c == ' '
- || c == '\t'
- )
- ) cp[ i ] = 0;
- if ( i < 0 || i > ( NSNLEN - 1 ) )
- { printf( "bad input line\n" );
- myexit ( 0 );
- }
- /* i == 0 prints them all. */
-
- for ( qp = workbuf; *cp; ++cp )
- { if ( *cp == '-' ) continue;
- c = *cp;
- if ( c >= 'A' && c <= 'Z' )
- { c ^= ( 'a' ^ 'A' ); /* tolower */
- }
- *qp++ = c;
- *qp = 0;
- }
- worklen = strlen( workbuf );
- for ( i = 0; i < nsentries; ++nsp, ++i )
- {
- wlen = nsp->nlen;
- if ( worklen > wlen )
- { /* if the string that the user entered is longer
- ** than the string in the table, this is a
- ** mismatch!
- */
- continue;
- }
-
- if ( worklen < wlen ) wlen = worklen;
- if ( ! strncmp( workbuf, nsp->nsname, wlen ))
- { printf( "%3d %s\n", nsp->nsnumber,
- nsp->nsoname );
- ns_matched = nsp;
- retcon( ++nmatch );
- continue;
- }
-
- for ( j = 0; j < nsp->nnoffs; ++j )
- { /* try pieces of the input name. */
- wlen = nsp->nlen - nsp->noff[j];
- if ( worklen > wlen ) break;
- if ( worklen < wlen ) wlen = worklen;
- if ( ! strncmp( workbuf,
- &nsp->nsname[ nsp->noff[j] ], wlen ))
- { printf( "%3d %s\n", nsp->nsnumber,
- nsp->nsoname );
- ns_matched = nsp;
- retcon( ++nmatch );
- break;
- }
- }
- }
- outa_here:
- printf( "===== %d matches\n", nmatch );
- return nmatch;
- }
- retcon( n )
- { if ( n % 23 ) return;
- printf( "[MORE]" );
- while ( ( n = getchar()) != '\n' && n != EOF );
- }
- struct
- { int UECSout;
- int KEYout;
- } out;
-
- dokey()
- { /* ns_matched is set to the nstab entry we need. */
- int result, i, c, flags, state;
- #define META 0x200
- #define CTLX 0x400
- #define MAGIC 0x100
-
- again:
- i = -1;
- flags = state = 0;
- printf( "Enter a keystroke sequence: " );
- while ( ( c = getchar()) != EOF && c != '\n' )
- { if ( state & 4 ) continue;
- switch ( c )
- { case '\r':
- case ' ':
- continue;
- case '^':
- if ( ! ( state & 1 ))
- { state |= 1;
- continue;
- }
- ctlchar: i = c & 0x1f;
- ctldel: state &= ~1;
- if ( ! ( state & 2 ))
- { /* first character */
- if ( i == ( 'x' & 0x1f ))
- { state |= 2;
- flags |= CTLX;
- continue;
- }
- if ( i == 0x1b )
- { state |= 2;
- flags |= META;
- continue;
- }
- if ( i == 1 )
- { state |= 2;
- flags |= MAGIC;
- continue;
- }
- state |= 4;
- continue;
- } /* else second character: */
- state |= 4;
- continue;
- case '?':
- if ( state & 1 )
- { i = 0x7f;
- goto ctldel;
- }
- default:
- i = c;
- if ( c < 0x20 || c > 0x7f ) continue;
- if ( state & 1 ) goto ctlchar;
- if ( ! ( state & 2 )) flags = -1;
- state |= 4;
- continue;
- }
- }
- switch ( flags )
- { case META:
- case CTLX:
- break;
- case 0:
- if ( ! ( i >= 0x20 && i <= 0x7f )) break;
- goto badseq;
- case MAGIC:
- if ( i >= 0x20 && i <= 0x7f ) break;
- default:
- badseq: printf( "Please try again\n" );
- goto again;
- }
- if ( i == -1 )
- { printf( "Okay, we'll skip this one.\n" );
- return;
- }
-
- out.UECSout = ns_matched->nsnumber;
- out.KEYout = i | flags;
- if ( write( outfile, &out, sizeof( out )) != sizeof( out ))
- { fprintf( stderr, "write error\n" );
- myexit( 1 );
- }
- printf( "The internal code 0x%x has been mapped to %d %s\n",
- i | flags, ns_matched->nsnumber, ns_matched->nsoname );
- }