1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #ifndef lint 13 static const char sccsid[] = "@(#)ex_abbrev.c 10.7 (Berkeley) 3/6/96"; 14 #endif /* not lint */ 15 16 #include <sys/types.h> 17 #include <sys/queue.h> 18 #include <sys/time.h> 19 20 #include <bitstring.h> 21 #include <ctype.h> 22 #include <limits.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include "../common/common.h" 28 #include "../vi/vi.h" 29 30 /* 31 * ex_abbr -- :abbreviate [key replacement] 32 * Create an abbreviation or display abbreviations. 33 * 34 * PUBLIC: int ex_abbr __P((SCR *, EXCMD *)); 35 */ 36 int 37 ex_abbr(sp, cmdp) 38 SCR *sp; 39 EXCMD *cmdp; 40 { 41 CHAR_T *p; 42 size_t len; 43 44 switch (cmdp->argc) { 45 case 0: 46 if (seq_dump(sp, SEQ_ABBREV, 0) == 0) 47 msgq(sp, M_INFO, "105|No abbreviations to display"); 48 return (0); 49 case 2: 50 break; 51 default: 52 abort(); 53 } 54 55 /* 56 * Check for illegal characters. 57 * 58 * !!! 59 * Another fun one, historically. See vi/v_ntext.c:txt_abbrev() for 60 * details. The bottom line is that all abbreviations have to end 61 * with a "word" character, because it's the transition from word to 62 * non-word characters that triggers the test for an abbreviation. In 63 * addition, because of the way the test is done, there can't be any 64 * transitions from word to non-word character (or vice-versa) other 65 * than between the next-to-last and last characters of the string, 66 * and there can't be any <blank> characters. Warn the user. 67 */ 68 if (!inword(cmdp->argv[0]->bp[cmdp->argv[0]->len - 1])) { 69 msgq(sp, M_ERR, 70 "106|Abbreviations must end with a \"word\" character"); 71 return (1); 72 } 73 for (p = cmdp->argv[0]->bp; *p != '\0'; ++p) 74 if (isblank(p[0])) { 75 msgq(sp, M_ERR, 76 "107|Abbreviations may not contain tabs or spaces"); 77 return (1); 78 } 79 if (cmdp->argv[0]->len > 2) 80 for (p = cmdp->argv[0]->bp, 81 len = cmdp->argv[0]->len - 2; len; --len, ++p) 82 if (inword(p[0]) != inword(p[1])) { 83 msgq(sp, M_ERR, 84 "108|Abbreviations may not mix word/non-word characters, except at the end"); 85 return (1); 86 } 87 88 if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len, 89 cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF)) 90 return (1); 91 92 F_SET(sp->gp, G_ABBREV); 93 return (0); 94 } 95 96 /* 97 * ex_unabbr -- :unabbreviate key 98 * Delete an abbreviation. 99 * 100 * PUBLIC: int ex_unabbr __P((SCR *, EXCMD *)); 101 */ 102 int 103 ex_unabbr(sp, cmdp) 104 SCR *sp; 105 EXCMD *cmdp; 106 { 107 ARGS *ap; 108 109 ap = cmdp->argv[0]; 110 if (!F_ISSET(sp->gp, G_ABBREV) || 111 seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) { 112 msgq_str(sp, M_ERR, ap->bp, 113 "109|\"%s\" is not an abbreviation"); 114 return (1); 115 } 116 return (0); 117 } 118