home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / kiface < prev    next >
Internet Message Format  |  1989-02-03  |  34KB

  1. Path: xanth!mcnc!rutgers!cmcl2!husc6!necntc!ncoast!allbery
  2. From: mjr@welchsun2.UUCP (Marcus J. Ranum)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i047: key mapping library for curses type applications
  5. Message-ID: <8806112005.AA08362@welchsun2>
  6. Date: 11 Jun 88 20:05:42 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: mjr@welchsun2.UUCP (Marcus J. Ranum)
  9. Lines: 1271
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. comp.sources.misc: Volume 3, Issue 47
  13. Submitted-By: "Marcus J. Ranum" <mjr@welchsun2.UUCP>
  14. Archive-Name: kiface
  15.  
  16. Key Interface Library
  17.  
  18. This library provides some fairly useful tools for mapping keys to
  19. return values that can be checked by a user interface, and acted
  20. upon. The idea is essentially to allow a program to assign a return
  21. value to a key, or a string of keys, so that a single returned value
  22. can be checked after a set of keys is input. IE: suppose we want to be
  23. able to support a 'generic UP key' that could be either '^P' for
  24. you EMACS fans, or '^[[A' for you with arrow keys that happen to return
  25. that.
  26.  
  27. ---chop---slice---dice---shred---chop---slice---dice---shred---chop---slice--
  28. #!/bin/sh
  29. #    This is a shell archive.
  30. #    run the file through sh.
  31. # shar:    Shell Archiver
  32. #    Run the following text with /bin/sh to create:
  33. #    README
  34. #    Makefile
  35. #    iface.h
  36. #    iface.3
  37. #    iface.c
  38. #    tester.c
  39. # This archive created: Sat Jun 11 16:02:20 1988
  40. echo shar: extracting README '(3032 characters)'
  41. sed 's/^XX//' << \SHAR_EOF > README
  42. XXKey Interface Library
  43. XX
  44. XXThis library provides some fairly useful tools for mapping keys to
  45. XX"return values" that can be checked by a user interface, and acted
  46. XXupon. The idea is essentially to allow a program to assign a return
  47. XXvalue to a key, or a string of keys, so that a single returned value
  48. XXcan be checked after a set of keys is input. IE: suppose we want to be
  49. XXable to support a 'generic UP key' that could be either '^P' for
  50. XXyou EMACS fans, or '^[[A' for you with arrow keys that happen to return
  51. XXthat.
  52. XX
  53. XXThere are some basic keys that must be supported for some of the
  54. XXroutines to work. The interface must be configured with at least
  55. XXa key that is defined to mean 'delete', as well as 'return', 'abort',
  56. XXand a few others. A function (that could be improved upon) is 
  57. XXprovided to establish this minimal set from termcap. Those of you
  58. XXwith bitmapped displays and windows systems will find this all to
  59. XXbe useless.
  60. XX
  61. XXThe main disadvantage with this package - (and it is a severe one!)
  62. XXis that I was not patient to do forward-looking in the mapping. If
  63. XXboth "foo" and "foobar" are defined, "foobar" will never be reached,
  64. XXsince "foo" will always return first. In practice, this may require 
  65. XXsome juggling. Right now, the code performs no checks against having
  66. XXoverlapped mappings, so you have the option to really screw yourself.
  67. XXI suppose something could be done with a timeout, and stuff like that,
  68. XXbut this is simpler and more likely to be portable. If anyone adds
  69. XXthis, please let me know :-)
  70. XX
  71. XXAn additional routine is provided to support input and line-editing of
  72. XXa buffer. This could be considerably enhanced depending on your display
  73. XXand if you're running curses, or whatever, but the demo program is
  74. XXas simple as possible. The intent of the ifgetstr() function is to
  75. XXallow something like:
  76. XX    
  77. XX    bufs[5][xx];
  78. XX    thisbuf = 0;
  79. XX
  80. XX    while(1) {
  81. XX        /* curses call to move cursor to beginning of bufs[thisbuf] */
  82. XX        /* wherever it lies on the screen */
  83. XX        ret = ifgetstr(&keymap,bufs[thisbuf],xx);
  84. XX        switch(ret) {
  85. XX            case IF_UPWRMOVE:
  86. XX                if(--thisbuf) < 0
  87. XX                    thisbuf = xx-1;
  88. XX                break;
  89. XX
  90. XX            case IF_DWNWMOVE:
  91. XX            case IF_CRETURN:
  92. XX                if(++thisbuf) > xx-1
  93. XX                    thisbuf = 0;
  94. XX                break;
  95. XX
  96. XX            case IF_ABORTKEY:
  97. XX                return(something);
  98. XX        }
  99. XX    }
  100. XX
  101. XXWhich would allow editing multiple buffers until an escape key was pressed.
  102. XX(note "esc" preceeds a lot of the arrow keys, see defect above)
  103. XXThere are loads of hooks in the code, including a pointer to where we
  104. XXleft off in the buffer, but use of such things should depend on the
  105. XXapplication. The ifgetstr() function is designed to be useful, but also
  106. XXto provide a basic starting point for more elaborate input management
  107. XXroutines.
  108. XX
  109. XXThis code is not public domain, though it is freely modifiable
  110. XXand distributable as long as the copyright notices are retained.  If
  111. XXyou make any nifty improvements, please let me know, (E-mail, I am not
  112. XXon usenet) bugfixes, etc, are welcome.
  113. XX
  114. XX 
  115. XX        Marcus J. Ranum, William Welch Medical Library, 1988
  116. XX        mjr@jhuigf.BITNET || uunet!mimsy!aplcen!osiris!welchvax!mjr
  117. SHAR_EOF
  118. if test 3032 -ne "`wc -c README`"
  119. then
  120. echo shar: error transmitting README '(should have been 3032 characters)'
  121. fi
  122. echo shar: extracting Makefile '(1094 characters)'
  123. sed 's/^XX//' << \SHAR_EOF > Makefile
  124. XX# Makefile for keyboard input library
  125. XX# Copyright(C) 1988, Marcus J. Ranum, William Welch Medical Library
  126. XX# 
  127. XX# $Header: Makefile,v 1.2 88/06/10 22:44:14 mjr rel $: Makefile 
  128. XX# 
  129. XX# $Log:    Makefile,v $
  130. XX# Revision 1.2  88/06/10  22:44:14  mjr
  131. XX# cleaned up some, added install option, other junk.
  132. XX# 
  133. XX# Revision 1.1  88/06/10  17:02:10  mjr
  134. XX# Initial revision
  135. XX# 
  136. XX# 
  137. XX
  138. XXLIBS= -ltermcap
  139. XXCFLAGS=-O
  140. XXLFLAGS=-s
  141. XXLINTFLAGS=-h -x -u
  142. XX
  143. XXLIB=    libiface.a
  144. XX
  145. XX# installation stuff
  146. XXLIBDIR=    /usr/local/lib
  147. XXHDR=    iface.h
  148. XXHDRDIR=    /usr/local/include
  149. XXMAN=    iface.3
  150. XXMANDIR=    /usr/man/manl
  151. XX
  152. XXall:    tester
  153. XX
  154. XXtester:        tester.o $(LIB)
  155. XX    cc $(LFLAGS) -o tester tester.o $(LIB) $(LIBS)
  156. XX
  157. XXclean:
  158. XX    rm -f *.o tester iface.shar $(LIB)
  159. XX
  160. XXlint:
  161. XX    lint $(LINTFLAGS) iface.c 
  162. XX
  163. XXshar:
  164. XX    shar -a README Makefile iface.h iface.3 iface.c tester.c > iface.shar
  165. XX
  166. XXinstall: $(LIB)
  167. XX    cp $(LIB) $(LIBDIR)/$(LIB)
  168. XX    chmod 644 $(LIBDIR)/$(LIB)
  169. XX    ranlib $(LIBDIR)/$(LIB)
  170. XX    cp $(HDR) $(HDRDIR)/$(HDR)
  171. XX    chmod 644 $(HDRDIR)/$(HDR)
  172. XX    cp $(MAN) $(MANDIR)/$(MAN)
  173. XX    chmod 644 $(MANDIR)/$(MAN)
  174. XX
  175. XXlibiface.a:    iface.o
  176. XX        ar rcv libiface.a iface.o
  177. XX        ranlib $@
  178. XX
  179. XXiface.o:    iface.c Makefile
  180. SHAR_EOF
  181. if test 1094 -ne "`wc -c Makefile`"
  182. then
  183. echo shar: error transmitting Makefile '(should have been 1094 characters)'
  184. fi
  185. echo shar: extracting iface.h '(2594 characters)'
  186. sed 's/^XX//' << \SHAR_EOF > iface.h
  187. XX/*
  188. XX * Copyright (C) 1988, Marcus J. Ranum, William Welch Medical Library
  189. XX * $Author: mjr $
  190. XX */
  191. XX
  192. XX/*
  193. XX * $Header: iface.h,v 1.3 88/06/11 15:58:53 mjr rel $: iface.h
  194. XX *
  195. XX * $Log:    iface.h,v $
  196. XX * Revision 1.3  88/06/11  15:58:53  mjr
  197. XX * added possibly useful macros. moved input buffer into map structure
  198. XX * 
  199. XX * Revision 1.2  88/06/10  22:45:43  mjr
  200. XX * improved readability of some comments.
  201. XX * 
  202. XX * Revision 1.1  88/06/10  17:02:00  mjr
  203. XX * Initial revision
  204. XX * 
  205. XX */
  206. XX
  207. XX#ifndef _INCL_IFACE_H
  208. XX
  209. XX/* size to hash key mappings into - a key mapping is stored in lexical */
  210. XX/* order, hashed based on the first character (hell of a hash, eh ?) */
  211. XX/* this really does not have to be a very big number */
  212. XX#define    IF_HSIZE    10
  213. XX
  214. XX/* size of input buffer */
  215. XX#define IF_INBUFSIZ    300
  216. XX
  217. XX/* a key mapping element */
  218. XXstruct    ifkey    {
  219. XX    char    *lhs;
  220. XX    int    rhs;
  221. XX    struct    ifkey    *next;
  222. XX};
  223. XX
  224. XX/* a command/key map */
  225. XXstruct    ifmap    {
  226. XX    struct    ifkey    *htab[IF_HSIZE];    /* key mapping entries */
  227. XX    int    hold;                /* holdover key */
  228. XX                        /* usually the key that */
  229. XX                        /* caused an error, or 0 */
  230. XX    int    lastret;            /* last recognized key */
  231. XX                        /* reset during getkey() */
  232. XX                        /* each time called */
  233. XX    int    lastbuf;            /* usable in ifgetstr() */
  234. XX                        /* - last position of curs */
  235. XX                        /* use at own risk */
  236. XX    char    inbuf[IF_INBUFSIZ];        /* input buffer - whatever */
  237. XX                        /* we currently have read */
  238. XX                        /* cleared in each call to */
  239. XX                        /* ifgetkey - may be long */
  240. XX};
  241. XX
  242. XX/* can be used to flush a pending character */
  243. XX#define    ifclearhold(map)    ((map).hold = '\0')
  244. XX#define    iflastch(map)        ((map).hold)
  245. XX#define    iflastret(map)        ((map).lastret)
  246. XX
  247. XX/* these are expected to be builtins - if you intend to use ifgetstr */
  248. XX/* these must be defined, at a minimum. (more can be). - to set up a */
  249. XX/* more or less "standard" set, you can use ifdfltmap() - which uses */
  250. XX/* some reasonable assumptions from termcap */
  251. XX#define    IF_NOTFOUND    -1    /* this one does not need to be bound ! */
  252. XX                /* since it is what we return when we are */
  253. XX                /* unable to find something interesting */
  254. XX#define    IF_DELCHAR    -2    /* we want to delete a character */
  255. XX#define    IF_BACKMOVE    -3    /* go backwards a char (nondestructive) */
  256. XX#define    IF_FORWMOVE    -4    /* go forward a char (nondestructive) */
  257. XX#define    IF_UPWRMOVE    -5    /* go up a char - sometimes can mean EOL */
  258. XX#define    IF_DWNWMOVE    -6    /* go down a char - sometimes can mean EOL */
  259. XX#define    IF_CRETURN    -7    /* return from input normally */
  260. XX#define    IF_ABORTKEY    -8    /* return from input with cancel */
  261. XX
  262. XX
  263. XXextern    void    ifinitmap();
  264. XXextern    void    ifdfltmap();
  265. XXextern    void    iffreemap();
  266. XXextern    struct    ifkey    *iflookup();
  267. XX
  268. XX#define _INCL_IFACE_H
  269. XX#endif
  270. SHAR_EOF
  271. if test 2594 -ne "`wc -c iface.h`"
  272. then
  273. echo shar: error transmitting iface.h '(should have been 2594 characters)'
  274. fi
  275. echo shar: extracting iface.3 '(8748 characters)'
  276. sed 's/^XX//' << \SHAR_EOF > iface.3
  277. XX.\" iface.3l (C)1988 Marcus J. Ranum, Welch Medical Library
  278. XX.\" $Header: iface.3,v 1.1 88/06/11 15:58:24 mjr rel $
  279. XX.TH IFACE 3l
  280. XX.SH NAME
  281. XXifinstall, ifdelete, ifgetkey, ifgetstr, ifdfltmap, iffreemap, ifinitmap, 
  282. XXiflookup, ifclearhold, iflastch, iflastret
  283. XX.br
  284. XX\- mappable key interface library
  285. XX.SH SYNTAX
  286. XX.B #include <local/iface.h>
  287. XX.PP
  288. XX.B int ifinstall(keymap,string,retval)
  289. XX.br
  290. XX.SM
  291. XX.B struct ifmap *keymap;
  292. XX.br
  293. XX.B char *string;
  294. XX.br
  295. XX.B int retval;
  296. XX.PP
  297. XX.B int ifdelete(keymap,string)
  298. XX.br
  299. XX.SM
  300. XX.B struct ifmap *keymap;
  301. XX.br
  302. XX.B char *string;
  303. XX.PP
  304. XX.B int ifgetkey(keymap)
  305. XX.br
  306. XX.SM
  307. XX.B struct ifmap *keymap;
  308. XX.PP
  309. XX.B int ifgetstr(keymap,buf,max,boffset)
  310. XX.br
  311. XX.SM
  312. XX.B struct ifmap *keymap;
  313. XX.br
  314. XX.B char *buf;
  315. XX.br
  316. XX.B int max, boffset;
  317. XX.PP
  318. XX.B void ifdfltmap(keymap)
  319. XX.br
  320. XX.SM
  321. XX.B struct ifmap *keymap;
  322. XX.PP
  323. XX.B void iffreemap(keymap)
  324. XX.br
  325. XX.SM
  326. XX.B struct ifmap *keymap;
  327. XX.PP
  328. XX.B void ifinitmap(keymap)
  329. XX.br
  330. XX.SM
  331. XX.B struct ifmap *keymap;
  332. XX.PP
  333. XX.B struct ifkey *iflookup(keymap,string)
  334. XX.br
  335. XX.SM
  336. XX.B struct ifmap *keymap;
  337. XX.br
  338. XX.B char *string;
  339. XX.PP
  340. XX.B (macro) ifclearhold(keymap)
  341. XX.br
  342. XX.SM
  343. XX.B struct ifmap *keymap;
  344. XX.PP
  345. XX.B (macro) iflastch(keymap)
  346. XX.br
  347. XX.SM
  348. XX.B struct ifmap *keymap;
  349. XX.PP
  350. XX.B (macro) iflastret(keymap)
  351. XX.br
  352. XX.SM
  353. XX.B struct ifmap *keymap;
  354. XX.PP
  355. XX.SH DESCRIPTION
  356. XX.PP
  357. XXThe mappable key interface library is designed to allow basic keymapping in
  358. XXapplications that rely on arrow keys, escape codes, etc. It is designed to
  359. XXgather keyboard input, looking for specific strings, and to return numerical
  360. XXcodes to indicate matches. Multiple mappings are supported, to allow many
  361. XXstrings to map to one return value. Every effort is made to minimize code
  362. XXsize and to maximize efficiency in string matching. The library includes 
  363. XXtools to allow basic key initialization, as well as deleting mappings,
  364. XXsearching mappings, and simple visual string editing. The primary shortcoming
  365. XXof the library is that a value is returned \fIas soon as a match is made\fP.
  366. XXThere is no effort to scan ahead, or timeout on input to try to figure
  367. XXwhat keys will be pressed next. This means that strings that are unique
  368. XXand short will always be matched before longer strings containing them.
  369. XXFor example, if "foo" is mapped to a value, "foobar" will never be matched,
  370. XXsince input will return at "foo". This becomes a problem when mapping
  371. XXsomething like the \fIesc\fP key, since the \fIesc\fP key preceeds many
  372. XXdesirable sequences such as arrow keys. This means that juggling on the
  373. XXpart of the user is necessary to prevent mapping useful keys to where 
  374. XXthey are inaccessible.
  375. XX.PP
  376. XXThe key mappings are all stored in a hashed linked list, in alphabetic
  377. XXorder. Dynamic memory allocation is used to maintain the list. Initially
  378. XXa mapping table has no keys mapped at all, and must be "prepped" with a
  379. XXcall to 
  380. XX.B ifinitmap
  381. XXto make sure everything is initialized properly. The library requires
  382. XXthat certain basic tokens be mapped (see \fIiface.h\fP) and provides a
  383. XXminimal function to set up some reasonable defaults from termcap values.
  384. XXUsers who do not like these values can assemble their own quite easily.
  385. XX.B Ifgetkey
  386. XXis the workhorse routine that performs matching of the mappings, and
  387. XXreturns values accordingly. Several additional values in the 
  388. XX.B ifmap
  389. XXstructure are used to hold information, including the last keypress
  390. XXin the event of a failure to match. This information can be accessed
  391. XXby the user to handle errors, or to perform default actions (see the
  392. XXcode in \fIiface.c\fP line \fI420\fP for an example). There are 
  393. XXmacros in \fIiface.h\fP that allow manipulation of these values,
  394. XXthough values and effects are not documented except in the source code.
  395. XX.PP
  396. XXThe
  397. XX.B ifinstall
  398. XXfunction installs
  399. XX.B string
  400. XXas a string in
  401. XX.B keymap
  402. XXwith a return code of
  403. XX.B retval.
  404. XXThere can be more than one string installed that returns
  405. XX.B retval.
  406. XX.B Ifinstall
  407. XXreturns 0 on success; -1 in the event of error. If the string already
  408. XXexists, the return value is modified to be
  409. XX.B retval.
  410. XX.PP
  411. XXThe
  412. XX.B ifdelete
  413. XXfunction removes the mapping string
  414. XX.B string
  415. XXfrom
  416. XX.B keymap,
  417. XXreturning 0 if it found and deleted something, -1 if it failed to
  418. XXfind the string.
  419. XX.PP
  420. XXThe 
  421. XX.B ifgetkey
  422. XXroutine is the main entry point to the library, performing the actual
  423. XXgathering of user input, and returning mapped values. 
  424. XX.B Ifgetkey
  425. XXassumes that input is being done in cbreak mode, presumably with
  426. XXnoecho set. Setting the terminal modes is the user's problem, and
  427. XXshould be handled elsewhere.
  428. XX.B  Ifgetkey
  429. XXreads characters, trying to match them against the mapped strings
  430. XXin
  431. XX.B keymap,
  432. XXreturning the installed integer value of found strings. If there is no
  433. XXmatch found, 
  434. XX.B ifgetkey
  435. XXreturns the default value
  436. XX.B IF_NOTFOUND
  437. XXwhich is defined in \fIiface.h\fP to be -1. Additional information
  438. XXabout what was found by
  439. XX.B ifgetkey
  440. XXcan be extracted from
  441. XX.B keymap.
  442. XXThere is an integer value
  443. XX.B keymap.hold
  444. XXwhich contains the last character read, and a character buffer
  445. XX.B keymap.inbuf
  446. XXwhich contains the current input string, in the even of a match that
  447. XXfailed after several characters. (IE - if we were trying to match "frobnitz"
  448. XXand only got "frobb", 
  449. XX.B keymap.ibuf
  450. XXwould have "frobb" stored in it, marking the point at which our input
  451. XXceased to match.)
  452. XXThe 
  453. XX.B ifclearhold
  454. XXand
  455. XX.B iflastch
  456. XXmacros allow access to these structures.
  457. XX.PP
  458. XXThe
  459. XX.B ifgetstr
  460. XXfunction is a building-block for a buffer editor. It uses the default
  461. XXkey mappings for upkey, downkey, etc, to handle editing of a character
  462. XXarray. Input is allowed until a return, abort, or up or down arrow
  463. XXis entered. The input is assembled into
  464. XX.B buf
  465. XXwith input being prohibited past
  466. XX.B max
  467. XXcharacters.
  468. XXThe argument
  469. XX.B boffset
  470. XXcan be given as a point within the buffer at which to begin the edit.
  471. XXIt is the \fIuser's\fP responsibility to initially "paint" the contents
  472. XXof 
  473. XX.B buf
  474. XXon the terminal in a desired location, before calling
  475. XX.B ifgetstr.
  476. XX.B Ifgetstr
  477. XXwill maintain its location on the screen by using backspaces, etc, to the
  478. XXbest of its ability, but if the user's application requires moving the
  479. XXcursor around, the results will be less than pretty. The intent of
  480. XXproviding
  481. XX.B ifgetstr
  482. XXis to demonstrate how these routines can be linked into something that
  483. XXis actually useful, rather than to provide a solution to string input 
  484. XXproblems.
  485. XX.PP
  486. XXThe
  487. XX.B ifdfltmap
  488. XXfunction builds a minimal "default" key mapping set into 
  489. XX.B keymap,
  490. XXusing termcap/termlib and whatever seems reasonable. This is also an
  491. XXexample routine, and far from definitive, but provides a minimal set of
  492. XXoperations. EMACS fans would probably prefer to map up, down, etc, to
  493. XXdifferent keys. Before calling
  494. XX.B ifdfltmap,
  495. XXthe keymap should be initialized using
  496. XX.B ifinitmap.
  497. XX.PP
  498. XXThe
  499. XXiffreemap
  500. XXfunction frees all (even the minimal) mappings in
  501. XX.B keymap.
  502. XXThis actually frees the dynamically allocated memory, and is completely
  503. XXdifferent in purpose from
  504. XX.B ifinitmap
  505. XXwhich only initializes the mapping hash table.
  506. XX.PP
  507. XXThe
  508. XX.B ifinitmap
  509. XXfunction makes sure that the hash table, etc, pointers in
  510. XX.B keymap
  511. XXare all properly blanked out. It should be called before the keymap
  512. XXis used, unless you are sure that everything is already set up properly.
  513. XXCalling
  514. XX.B ifinitmap
  515. XXon a keymap with entries added will not free any memory that has been
  516. XXallocated.
  517. XX.PP
  518. XXThe
  519. XX.B iflookup
  520. XXfunction returns a pointer to a structure of type
  521. XX.B ifmap,
  522. XXor to NULL, depending on whether there is a match for
  523. XX.B string
  524. XXin
  525. XX.B keymap
  526. XXor not. This routine is provided for completeness, not because I can
  527. XXthink of much use for it. (otherwise, it can be inlined into 
  528. XX.B ifinstall
  529. XXif you like)
  530. XX.PP
  531. XXThe
  532. XX.B ifclearhold,
  533. XX.B iflastch,
  534. XXand
  535. XX.B iflastret
  536. XXmacros allow easy access to the various bits of information retained
  537. XXin 
  538. XX.B keymap.
  539. XX.B Ifclearhold
  540. XXsets the held character to 0, which prevents 
  541. XX.B ifgetkey
  542. XXfrom trying to use it to complete the next match. For example, if the
  543. XXprogram is trying to match "foo" and gets "fg", the 'g' is retained
  544. XXin 
  545. XX.B keymap.hold
  546. XXto use as the first input character for the next call to
  547. XX.B ifgetkey.
  548. XXThis is sometimes not desirable. The 
  549. XX.B iflastch
  550. XXmacro allows access to this last character, if desired, but does not
  551. XXclear it. The
  552. XX.B iflastret
  553. XXmacro allows access to whatever 
  554. XX.B ifgetkey
  555. XXlast \fIreturned\fP. This is included for logical completeness. It is
  556. XXreset during every call to
  557. XX.B ifgetkey.
  558. XX.PP
  559. XX.SH RESTRICTIONS
  560. XX.PP
  561. XXIf two mappings completely overlap, the longer will never be returned
  562. XXsince the shorter one will always match first. Thus, "foo" and "foobar"
  563. XXwill cause "foo" to always match first, even if "foobar" is typed. Mappings
  564. XXsuch as "foop" and "foobar" will not conflict.
  565. XX.PP
  566. XXThis library is useless to anyone with a higher-level window management
  567. XXsystem.
  568. XX.SH DIAGNOSTICS
  569. XX.PP
  570. XX.SH AUTHOR
  571. XX.PP
  572. XXMarcus J. Ranum, Welch Medical Library.
  573. XX.br
  574. XX.ti 1i
  575. XXuunet!aplcen!osiris!welchvax!mjr
  576. XX.br
  577. XX.ti 1i
  578. XXmjr@jhuigf.BITNET
  579. XX.SH SEE ALSO
  580. SHAR_EOF
  581. if test 8748 -ne "`wc -c iface.3`"
  582. then
  583. echo shar: error transmitting iface.3 '(should have been 8748 characters)'
  584. fi
  585. echo shar: extracting iface.c '(8279 characters)'
  586. sed 's/^XX//' << \SHAR_EOF > iface.c
  587. XX/*
  588. XX * Copyright (C) 1988, Marcus J. Ranum, William Welch Medical Library
  589. XX * $Author: mjr $
  590. XX */
  591. XX
  592. XX#ifndef lint
  593. XXstatic char *RCSid="$Header: iface.c,v 1.3 88/06/11 15:58:32 mjr rel $: iface.c";
  594. XX#endif
  595. XX
  596. XX/*
  597. XX * $Log:    iface.c,v $
  598. XX * Revision 1.3  88/06/11  15:58:32  mjr
  599. XX * added better initializations to ifinitmap
  600. XX * 
  601. XX * Revision 1.2  88/06/10  22:45:14  mjr
  602. XX * added option to edit a buffer from an arbitrary point in the buffer.
  603. XX * 
  604. XX * Revision 1.1  88/06/10  17:01:40  mjr
  605. XX * Initial revision
  606. XX * 
  607. XX */
  608. XX
  609. XX#include    <stdio.h>
  610. XX#include    "iface.h"
  611. XX
  612. XX
  613. XX
  614. XX/* free a key map table - this zaps all mappings totally */
  615. XXvoid
  616. XXiffreemap(kmap)
  617. XXstruct    ifmap    *kmap;
  618. XX{
  619. XX    int    x;
  620. XX    struct    ifkey    *kp;
  621. XX    struct    ifkey    *xp;
  622. XX    
  623. XX    for(x = 0; x < IF_HSIZE; x++) {
  624. XX        kp = kmap->htab[x]; 
  625. XX        while(kp != NULL) {
  626. XX            xp = kp->next;
  627. XX            (void)free(kp->lhs);
  628. XX            (void)free((char *)kp);
  629. XX            kp = xp;
  630. XX        }
  631. XX        kmap->htab[x] = NULL;
  632. XX    }
  633. XX}
  634. XX
  635. XX
  636. XX
  637. XX/* clear a key map table - this prepares the table for adding mappings */
  638. XXvoid
  639. XXifinitmap(kmap)
  640. XXstruct    ifmap    *kmap;
  641. XX{
  642. XX    int    x;
  643. XX    
  644. XX    /* all we do here is set the hash entries to NULL */
  645. XX    /* THIS IS NOT THE SAME AS FREEING ALL THE MAP ENTRIES */
  646. XX    /* call this when a map table is first created, call iffreemap() */
  647. XX    /* if you want to deallocate a mapping table */
  648. XX    for(x = 0; x < IF_HSIZE; x++)
  649. XX        kmap->htab[x] = NULL;
  650. XX
  651. XX    /* set these, too */
  652. XX    kmap->hold = '\0';
  653. XX    kmap->lastret = -1;
  654. XX    kmap->lastbuf = 0;
  655. XX    kmap->inbuf[0] = '\0';
  656. XX}
  657. XX
  658. XX
  659. XX/* install a default key map table - or most of one */
  660. XXvoid
  661. XXifdfltmap(kmap)
  662. XXstruct    ifmap    *kmap;
  663. XX{
  664. XX    char    tbuf[1024];
  665. XX    char    fill[1024];
  666. XX    char    *fptr = fill;
  667. XX    char    *forch;
  668. XX    char    *uprch;
  669. XX    char    *bwrch;
  670. XX    char    *dnrch;
  671. XX    char    *crch;
  672. XX    static    char    hbuf[2];
  673. XX    static    char    *dforch = "\33[C";
  674. XX    static    char    *duprch = "\33[A";
  675. XX    static    char    *dbwrch = "\33[D";
  676. XX    static    char    *ddnrch = "\33[B";
  677. XX    static    char    *dcrch = "\n";
  678. XX    extern    char    *getenv();
  679. XX    extern    char    *tgetstr();
  680. XX
  681. XX    if(((forch = getenv("TERM")) != NULL) && (tgetent(tbuf,forch) == 1)) {
  682. XX        if((forch = tgetstr("kr",&fptr)) == 0)
  683. XX            forch = dforch;
  684. XX        if((uprch = tgetstr("ku",&fptr)) == 0)
  685. XX            uprch = duprch;
  686. XX        if((bwrch = tgetstr("kl",&fptr)) == 0)
  687. XX            bwrch = dbwrch;
  688. XX        if((dnrch = tgetstr("kd",&fptr)) == 0)
  689. XX            dnrch = ddnrch;
  690. XX        if((crch = tgetstr("cr",&fptr)) == 0)
  691. XX            crch = dcrch;
  692. XX    } else {
  693. XX        /* could get terminal entry - use whatever */
  694. XX        forch = dforch;
  695. XX        uprch = duprch;
  696. XX        bwrch = dbwrch;
  697. XX        dnrch = ddnrch;
  698. XX        crch = dcrch;
  699. XX    }
  700. XX
  701. XX    /* install the foogers */
  702. XX    hbuf[0] = 127;
  703. XX    hbuf[1] = '\0';
  704. XX    (void)ifinstall(kmap,hbuf,IF_DELCHAR);
  705. XX    (void)ifinstall(kmap,"\b",IF_DELCHAR);
  706. XX    (void)ifinstall(kmap,bwrch,IF_BACKMOVE);
  707. XX    (void)ifinstall(kmap,forch,IF_FORWMOVE);
  708. XX    (void)ifinstall(kmap,uprch,IF_UPWRMOVE);
  709. XX    (void)ifinstall(kmap,dnrch,IF_DWNWMOVE);
  710. XX    (void)ifinstall(kmap,crch,IF_CRETURN);
  711. XX    return;
  712. XX}
  713. XX
  714. XX
  715. XX
  716. XX/* look the bad boy up */
  717. XXstruct    ifkey    *
  718. XXiflookup(kmap,s)
  719. XXstruct    ifmap    *kmap;
  720. XXchar    *s;
  721. XX{
  722. XX    struct    ifkey    *kp;
  723. XX    for(kp = kmap->htab[*s % IF_HSIZE]; kp != NULL; kp = kp->next)
  724. XX        if(strcmp(s,kp->lhs) == 0)
  725. XX            return(kp);
  726. XX    return(NULL);
  727. XX}
  728. XX    
  729. XX
  730. XX
  731. XX/* install a key mapping, hashed, and in lexical order */
  732. XXifinstall(kmap,lh,rh)
  733. XXstruct    ifmap    *kmap;
  734. XXchar    *lh;
  735. XXint    rh;
  736. XX{
  737. XX    struct    ifkey    *kp;
  738. XX    struct    ifkey    *after;
  739. XX    extern    char    *malloc();
  740. XX    extern    char    *strcpy();
  741. XX    
  742. XX    /* not found - install anew */
  743. XX    if((kp = iflookup(kmap,lh)) == NULL) {
  744. XX
  745. XX        /* figure out where to put it */
  746. XX        kp = kmap->htab[*lh % IF_HSIZE];
  747. XX        after = NULL;
  748. XX        while(kp != NULL) {
  749. XX            if(strcmp(lh,kp->lhs) < 0)
  750. XX                break;
  751. XX            after = kp;
  752. XX            kp = kp->next;
  753. XX        }
  754. XX
  755. XX/* avoid the possible pointer alignment problem message */
  756. XX#ifndef lint
  757. XX        /* allocate it */
  758. XX        kp = (struct ifkey *)malloc(sizeof(struct ifkey));
  759. XX#else
  760. XX        kp = NULL;
  761. XX#endif
  762. XX        if(kp == NULL)
  763. XX            return(-1);
  764. XX        kp->lhs = malloc((unsigned)strlen(lh));
  765. XX        if(kp->lhs == NULL)
  766. XX            return(-1);
  767. XX        kp->rhs = rh;
  768. XX        (void)strcpy(kp->lhs,lh);
  769. XX
  770. XX        /* fixup sibling pointers */
  771. XX        if(after != NULL) {
  772. XX                kp->next = after->next;
  773. XX                after->next = kp;
  774. XX        } else {
  775. XX            if(kmap->htab[*lh % IF_HSIZE] != NULL) {
  776. XX                kp->next = kmap->htab[*lh % IF_HSIZE];
  777. XX                kmap->htab[*lh % IF_HSIZE] = kp;
  778. XX            } else {
  779. XX                kmap->htab[*lh % IF_HSIZE] = kp;
  780. XX                kp->next = NULL;
  781. XX            }
  782. XX        }
  783. XX    } else {
  784. XX        /* just change the return value */
  785. XX        kp->rhs = rh;
  786. XX    }
  787. XX
  788. XX    return(0);
  789. XX}
  790. XX    
  791. XX
  792. XX
  793. XX/* de-install a key mapping (by key string) */
  794. XXifdelete(kmap,s)
  795. XXstruct    ifmap    *kmap;
  796. XXchar    *s;
  797. XX{
  798. XX    struct    ifkey    *kp;
  799. XX    struct    ifkey    *lptr = NULL;
  800. XX    extern    char    *strcpy();
  801. XX    
  802. XX    for(kp = kmap->htab[*s % IF_HSIZE]; kp != NULL; kp = kp->next) {
  803. XX        if(strcmp(s,kp->lhs) == 0) {
  804. XX            if(lptr != NULL) {
  805. XX                /* last node next points to the next one */
  806. XX                lptr->next = kp->next;
  807. XX            } else {
  808. XX                /* root node next points to the next one */
  809. XX                kmap->htab[*s % IF_HSIZE] = kp->next;
  810. XX            }
  811. XX            (void)free(kp->lhs);
  812. XX            (void)free((char *)kp);
  813. XX            return(0);
  814. XX        }
  815. XX        lptr = kp;
  816. XX    }
  817. XX    return(-1);
  818. XX}
  819. XX
  820. XX
  821. XX
  822. XXifgetkey(kmap)
  823. XXstruct    ifmap    *kmap;
  824. XX{
  825. XX    int    c =0;
  826. XX    int    nfound;    
  827. XX    int    nclose;    
  828. XX    char    *i;
  829. XX    char    *o;
  830. XX    int    cnt =0;
  831. XX    int    xcnt;
  832. XX    struct    ifkey    *kp;        /* current key pointer */
  833. XX    struct    ifkey    *bp = NULL;    /* bottom closest match pointer */
  834. XX    struct    ifkey    *ret = NULL;    /* our match */
  835. XX
  836. XX
  837. XX    while(1) {
  838. XX        if((c = getchar()) == EOF) {
  839. XX            kmap->lastret = IF_NOTFOUND;
  840. XX            kmap->hold = c;
  841. XX            return(IF_NOTFOUND);
  842. XX        }
  843. XX
  844. XX        /* should happen once and only once per call */
  845. XX        /* we set the bottom pointer to point to just before */
  846. XX        /* the first char of our input stream */
  847. XX        if(bp == NULL) {
  848. XX            bp = kmap->htab[c % IF_HSIZE]; 
  849. XX
  850. XX            /* nothing in this hash chain to find */
  851. XX            if(bp == NULL) {
  852. XX                kmap->lastret = IF_NOTFOUND;
  853. XX                kmap->hold = c;
  854. XX                return(IF_NOTFOUND);
  855. XX            }
  856. XX            
  857. XX            /* otherwise skate or die */
  858. XX            while(bp->next != NULL && c > *bp->lhs)
  859. XX                bp = bp->next;
  860. XX        }
  861. XX
  862. XX
  863. XX        nfound = 0;
  864. XX        nclose = 0;
  865. XX        kp = bp;
  866. XX
  867. XX        if(cnt + 1 > IF_INBUFSIZ)
  868. XX            return(-1);
  869. XX
  870. XX        kmap->inbuf[cnt++] = c;
  871. XX        kmap->inbuf[cnt] = '\0';
  872. XX
  873. XX        while(kp != NULL) {
  874. XX
  875. XX            xcnt = 0;
  876. XX            o = kp->lhs;
  877. XX            i = kmap->inbuf;
  878. XX
  879. XX            if(*o != *i)
  880. XX                break;
  881. XX
  882. XX            /* a mix of strcmp and strncmp */
  883. XX            for(; *o == *i; o++, i++, xcnt++) {
  884. XX                if(*o == '\0') {
  885. XX                    nfound++;
  886. XX                    ret = kp;
  887. XX                    break;
  888. XX                }
  889. XX            }
  890. XX            if(xcnt == cnt)
  891. XX                nclose++;
  892. XX            kp = kp->next;
  893. XX        }
  894. XX
  895. XX        /* didn't find any !! - unmapped key */
  896. XX        if(nfound == 0 && nclose == 0) {
  897. XX            kmap->hold = c;
  898. XX            kmap->lastret = IF_NOTFOUND;
  899. XX            return(IF_NOTFOUND);
  900. XX        }
  901. XX
  902. XX        /* only found one - great! */
  903. XX        if(nfound) {
  904. XX            kmap->hold = '\0';
  905. XX            kmap->lastret = ret->rhs;
  906. XX            return(ret->rhs);
  907. XX        }
  908. XX    }
  909. XX}
  910. XX
  911. XX
  912. XX
  913. XXifgetstr(kmap,buf,max,bpos)
  914. XXstruct    ifmap    *kmap;
  915. XXchar    buf[];
  916. XXint    max;
  917. XXint    bpos;
  918. XX{
  919. XX    int    c =0;        /* input returned char */
  920. XX    int    high =0;    /* line high water mark */
  921. XX    int    cnt =0;        /* current position/count */
  922. XX
  923. XX    high = strlen(buf);
  924. XX    if(bpos > high)
  925. XX        cnt = high;
  926. XX    else
  927. XX        cnt = bpos;
  928. XX
  929. XX    while(1) {
  930. XX
  931. XX        /* get a key from the map */
  932. XX        switch(c = ifgetkey(kmap)) {
  933. XX
  934. XX                /* delete a character */
  935. XX            case IF_DELCHAR:
  936. XX                /* if at current high water mark */
  937. XX
  938. XX                /* if at beginning of line */
  939. XX                if(cnt - 1 < 0) {
  940. XX                    (void)fputc(07,stderr);
  941. XX                } else {
  942. XX                    if(cnt == high) {
  943. XX                        high = --cnt;
  944. XX                        buf[cnt] = 0;
  945. XX                    } else {
  946. XX                        buf[--cnt] = ' ';
  947. XX                    }
  948. XX                    (void)fprintf(stderr,"\b \b");
  949. XX                }
  950. XX                break;
  951. XX
  952. XX
  953. XX                /* NON-DESTRUCTIVE backwards move */
  954. XX            case IF_BACKMOVE:
  955. XX                if(cnt - 1 < 0) {
  956. XX                    (void)fputc(07,stderr);
  957. XX                } else {
  958. XX                    cnt--;
  959. XX                    (void)fprintf(stderr,"\b");
  960. XX                }
  961. XX                break;
  962. XX
  963. XX
  964. XX                /* NON-DESTRUCTIVE forward move */
  965. XX            case IF_FORWMOVE:
  966. XX                if(cnt + 1 > max) {
  967. XX                    (void)fputc(07,stderr);
  968. XX                } else {
  969. XX                    if(high == cnt) {
  970. XX                        buf[cnt] = ' ';
  971. XX                        high = ++cnt;
  972. XX                    } else {
  973. XX                        ++cnt;
  974. XX                    }
  975. XX                    (void)fputc(buf[cnt - 1],stderr);
  976. XX                }
  977. XX                break;
  978. XX
  979. XX
  980. XX                /* FINISHED */
  981. XX            case IF_CRETURN:
  982. XX                buf[high] = '\0';
  983. XX                kmap->lastbuf = cnt;
  984. XX                return(IF_CRETURN);
  985. XX
  986. XX
  987. XX                /* DOWN */
  988. XX            case IF_DWNWMOVE:
  989. XX                buf[high] = '\0';
  990. XX                kmap->lastbuf = cnt;
  991. XX                return(IF_DWNWMOVE);
  992. XX
  993. XX
  994. XX                /* UP */
  995. XX            case IF_UPWRMOVE:
  996. XX                buf[high] = '\0';
  997. XX                kmap->lastbuf = cnt;
  998. XX                return(IF_UPWRMOVE);
  999. XX
  1000. XX
  1001. XX                /* abort */
  1002. XX            case IF_ABORTKEY:
  1003. XX                buf[0] = '\0';
  1004. XX                kmap->lastbuf = cnt;
  1005. XX                return(IF_ABORTKEY);
  1006. XX
  1007. XX
  1008. XX                /* must be a character insert */
  1009. XX            case IF_NOTFOUND:
  1010. XX                c = kmap->hold;
  1011. XX                kmap->hold = '\0';
  1012. XX                if(cnt + 1 > max) {
  1013. XX                    (void)fputc(07,stderr);
  1014. XX                    buf[cnt] = '\0';
  1015. XX                } else {
  1016. XX                    buf[cnt] = c;
  1017. XX                    (void)fputc(c,stderr);
  1018. XX                    if(high == cnt)
  1019. XX                        high = ++cnt;
  1020. XX                    else
  1021. XX                        ++cnt;
  1022. XX                }
  1023. XX                break;
  1024. XX        }
  1025. XX    }
  1026. XX}
  1027. SHAR_EOF
  1028. if test 8279 -ne "`wc -c iface.c`"
  1029. then
  1030. echo shar: error transmitting iface.c '(should have been 8279 characters)'
  1031. fi
  1032. echo shar: extracting tester.c '(4851 characters)'
  1033. sed 's/^XX//' << \SHAR_EOF > tester.c
  1034. XX/*
  1035. XX * Copyright (C) 1988, Marcus J. Ranum, William Welch Medical Library
  1036. XX * $Author: mjr $
  1037. XX */
  1038. XX
  1039. XX#ifndef lint
  1040. XXstatic char *RCSid="$Header: tester.c,v 1.2 88/06/10 22:46:12 mjr rel $: tester.c";
  1041. XX#endif
  1042. XX
  1043. XX/*
  1044. XX * $Log:    tester.c,v $
  1045. XX * Revision 1.2  88/06/10  22:46:12  mjr
  1046. XX * added example of function calling, buffer edit.
  1047. XX * 
  1048. XX * Revision 1.1  88/06/10  17:01:51  mjr
  1049. XX * Initial revision
  1050. XX * 
  1051. XX */
  1052. XX
  1053. XX#include <stdio.h>
  1054. XX#include <sys/ioctl.h>
  1055. XX#include "iface.h"
  1056. XX
  1057. XX#define EDBUFSIZ    100
  1058. XX
  1059. XX/* for the sake of example - a decent way to use this library */
  1060. XX/* obviously, you really should build a structure with pointers to */
  1061. XX/* functions and everything - then call the iface. exercise for the */
  1062. XX/* reader */
  1063. XX#define    TEST_DOTHIS    1
  1064. XXextern    void    dothis();
  1065. XX#define    TEST_DOTHAT    2
  1066. XXextern    void    dothat();
  1067. XX#define    TEST_DONADA    3
  1068. XXextern    void    donada();
  1069. XX
  1070. XXmain()
  1071. XX{
  1072. XX    char    instr[BUFSIZ];
  1073. XX    int    c;
  1074. XX    char    buf[BUFSIZ];
  1075. XX    char    edbuf[EDBUFSIZ];
  1076. XX    int    ret;
  1077. XX    struct    ifmap    keymap;
  1078. XX    struct    ifkey    *keyp;
  1079. XX    struct    sgttyb    ttybuf;
  1080. XX    extern    void    igets();
  1081. XX    extern    char    *strcpy();
  1082. XX
  1083. XX    ifinitmap(&keymap);
  1084. XX    ifdfltmap(&keymap);
  1085. XX
  1086. XX    /* for edit demo */
  1087. XX    (void)strcpy(edbuf,"Edit This !:");
  1088. XX
  1089. XX
  1090. XX    /* install dothis, dothat, donada - to "1", "2" and "3" */
  1091. XX    if(ifinstall(&keymap,"1",TEST_DOTHIS) != 0)
  1092. XX        (void)printf("error!\n");
  1093. XX    if(ifinstall(&keymap,"2",TEST_DOTHAT) != 0)
  1094. XX        (void)printf("error!\n");
  1095. XX    if(ifinstall(&keymap,"3",TEST_DONADA) != 0)
  1096. XX        (void)printf("error!\n");
  1097. XX
  1098. XX    /* you have to handle putting the terminal is noecho cbreak */
  1099. XX    if(ioctl(0,TIOCGETP,(char *)&ttybuf) < 0)
  1100. XX        perror("ioctl - GETP");
  1101. XX    ttybuf.sg_flags |= CBREAK;
  1102. XX    ttybuf.sg_flags &= ~ECHO;
  1103. XX    if(ioctl(0,TIOCSETP,(char *)&ttybuf) <0)
  1104. XX        perror("ioctl - SETP");
  1105. XX
  1106. XX
  1107. XX    /* main demo loop */
  1108. XX    while (1) {
  1109. XX        (void)printf("\nEdit  Run  Install  Search  Delete  GetKey   Line   Quit:");
  1110. XX        if((c = getchar()) == NULL) {
  1111. XX            (void)printf("\n");
  1112. XX            exit(0);
  1113. XX        }
  1114. XX
  1115. XX        switch (c) {
  1116. XX
  1117. XX        /* quit */
  1118. XX        case 'q':
  1119. XX        case 'Q':
  1120. XX            ttybuf.sg_flags &= ~CBREAK;
  1121. XX            ttybuf.sg_flags |= ECHO;
  1122. XX            if(ioctl(0,TIOCSETP,(char *)&ttybuf) <0)
  1123. XX                perror("ioctl - SETP");
  1124. XX            (void)printf("\n");
  1125. XX            exit(0);
  1126. XX            
  1127. XX
  1128. XX        /* edit a string */
  1129. XX        case 'e':
  1130. XX        case 'E':
  1131. XX            (void)printf("\n%s",edbuf);
  1132. XX            ret = ifgetstr(&keymap,edbuf,EDBUFSIZ,EDBUFSIZ);
  1133. XX            switch(ret) {
  1134. XX                case IF_UPWRMOVE:
  1135. XX                    (void)printf("\n(up)got:\"%s\"\n",edbuf);
  1136. XX                    break;
  1137. XX
  1138. XX                case IF_DWNWMOVE:
  1139. XX                    (void)printf("\n(down)got:\"%s\"\n",edbuf);
  1140. XX                    break;
  1141. XX
  1142. XX                case IF_CRETURN:
  1143. XX                    (void)printf("\n(return)got:\"%s\"\n",edbuf);
  1144. XX                    break;
  1145. XX
  1146. XX                case IF_ABORTKEY:
  1147. XX                    (void)printf("\n(abort)got:\"%s\"\n",edbuf);
  1148. XX                    break;
  1149. XX
  1150. XX                default:
  1151. XX                    (void)printf("\n(err)got:\"%s\"\n",edbuf);
  1152. XX                    break;
  1153. XX            }
  1154. XX            break;
  1155. XX            
  1156. XX
  1157. XX        case 'r':
  1158. XX        case 'R':
  1159. XX            (void)printf("\ncommand ? (press 1, 2, or 3):");
  1160. XX            ret = ifgetkey(&keymap);
  1161. XX            switch(ret) {
  1162. XX                case TEST_DOTHIS:
  1163. XX                        dothis();
  1164. XX                        break;
  1165. XX                case TEST_DOTHAT:
  1166. XX                        dothat();
  1167. XX                        break;
  1168. XX                case TEST_DONADA:
  1169. XX                        donada();
  1170. XX                        break;
  1171. XX                case IF_NOTFOUND:
  1172. XX                        (void)printf("\nI said, 1, 2, or 3\n");
  1173. XX                        break;
  1174. XX                default:
  1175. XX                        (void)printf("\nwhassat ?\n");
  1176. XX            }
  1177. XX            break;
  1178. XX
  1179. XX
  1180. XX        /* search for a mapping entry */
  1181. XX        case 's':
  1182. XX        case 'S':
  1183. XX            (void)printf("\nSearch for:");
  1184. XX            (void)igets(buf,&ttybuf);
  1185. XX            keyp = iflookup(&keymap,buf);
  1186. XX            if(keyp == NULL)
  1187. XX                (void)printf("\nnot found\n");
  1188. XX            else
  1189. XX                (void)printf("\nKval:%d\n",keyp->rhs);
  1190. XX            break;
  1191. XX
  1192. XX
  1193. XX        /* install a mapping entry */
  1194. XX        case 'i':
  1195. XX        case 'I':
  1196. XX            (void)printf("\nNumber:");
  1197. XX            (void)igets(buf,&ttybuf);
  1198. XX            ret = atoi(buf);
  1199. XX            (void)printf("Install string:");
  1200. XX            (void)igets(buf,&ttybuf);
  1201. XX            if(ifinstall(&keymap,buf,ret) != 0)
  1202. XX                (void)printf("error!\n");
  1203. XX            break;
  1204. XX            
  1205. XX
  1206. XX        /* enter a line of junk */
  1207. XX        case 'L':
  1208. XX        case 'l':
  1209. XX            (void)printf("\nEnter Stuff:");
  1210. XX            ret = ifgetstr(&keymap,instr,BUFSIZ,0);
  1211. XX            if(ret != 0)
  1212. XX                (void)printf("\nabort..\n");
  1213. XX            else
  1214. XX                (void)printf("\ngot:\"%s\"\n",instr);
  1215. XX            break;
  1216. XX            
  1217. XX        /* get a key in "raw" mode */
  1218. XX        case 'g':
  1219. XX        case 'G':
  1220. XX            ifclearhold(keymap);
  1221. XX            (void)printf("\ngo:\n",ret);
  1222. XX            while((ret = ifgetkey(&keymap)) != IF_NOTFOUND)        
  1223. XX                (void)printf("\n%d",ret);
  1224. XX            (void)printf("\n(done)\n",ret);
  1225. XX            break;
  1226. XX
  1227. XX
  1228. XX        /* delete a map entry */
  1229. XX        case 'd':
  1230. XX        case 'D':
  1231. XX            (void)printf("\nDelete string:");
  1232. XX            (void)igets(buf,&ttybuf);
  1233. XX            if(ifdelete(&keymap,buf) != 0)
  1234. XX                (void)printf("error!\n");
  1235. XX            break;
  1236. XX
  1237. XX        default:
  1238. XX            (void)printf("\nhuh?\n");
  1239. XX        }
  1240. XX    }
  1241. XX}
  1242. XX
  1243. XXvoid
  1244. XXigets(buf,ttybuf)
  1245. XXchar    buf[];
  1246. XXstruct    sgttyb    *ttybuf;
  1247. XX{
  1248. XX    ttybuf->sg_flags &= ~CBREAK;
  1249. XX    ttybuf->sg_flags |= ECHO;
  1250. XX    if(ioctl(0,TIOCSETP,(char *)ttybuf) <0)
  1251. XX        perror("ioctl - SETP");
  1252. XX    (void)gets(buf);
  1253. XX    ttybuf->sg_flags |= CBREAK;
  1254. XX    ttybuf->sg_flags &= ~ECHO;
  1255. XX    if(ioctl(0,TIOCSETP,(char *)ttybuf) <0)
  1256. XX        perror("ioctl - SETP");
  1257. XX}
  1258. XX
  1259. XXvoid
  1260. XXdothis()
  1261. XX{
  1262. XX    (void)printf("\ndothis called");
  1263. XX}
  1264. XX
  1265. XXvoid
  1266. XXdothat()
  1267. XX{
  1268. XX    (void)printf("\ndothat called");
  1269. XX}
  1270. XX
  1271. XXvoid
  1272. XXdonada()
  1273. XX{
  1274. XX    (void)printf("\ndonada called");
  1275. XX}
  1276. SHAR_EOF
  1277. if test 4851 -ne "`wc -c tester.c`"
  1278. then
  1279. echo shar: error transmitting tester.c '(should have been 4851 characters)'
  1280. fi
  1281. #    End of shell archive
  1282. exit 0
  1283.