xref: /illumos-gate/usr/src/tools/cscope-fast/input.c (revision e0731422366620894c16c1ee6515551c5f00733d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*	Copyright (c) 1988 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 /*
30  *	cscope - interactive C symbol cross-reference
31  *
32  *	terminal input functions
33  */
34 
35 #include "global.h"
36 #include <curses.h>	/* KEY_BACKSPACE, KEY_BREAK, and KEY_ENTER */
37 #include <setjmp.h>	/* jmp_buf */
38 
39 static	jmp_buf	env;		/* setjmp/longjmp buffer */
40 static	int	prevchar;	/* previous, ungotten character */
41 
42 /* catch the interrupt signal */
43 
44 /*ARGSUSED*/
45 SIGTYPE
46 catchint(int sig)
47 {
48 	(void) signal(SIGINT, catchint);
49 	longjmp(env, 1);
50 }
51 
52 /* unget a character */
53 
54 int
55 ungetch(int c)
56 {
57 	prevchar = c;
58 	return (0);
59 }
60 
61 /* get a character from the terminal */
62 
63 int
64 mygetch(void)
65 {
66 	SIGTYPE	(*savesig)();		/* old value of signal */
67 	int	c;
68 
69 	/* change an interrupt signal to a break key character */
70 	if (setjmp(env) == 0) {
71 		savesig = signal(SIGINT, catchint);
72 		(void) refresh();	/* update the display */
73 		reinitmouse();	/* curses can change the menu number */
74 		if (prevchar) {
75 			c = prevchar;
76 			prevchar = 0;
77 		} else {
78 			c = getch();	/* get a character from the terminal */
79 		}
80 	} else {	/* longjmp to here from signal handler */
81 		c = KEY_BREAK;
82 	}
83 	(void) signal(SIGINT, savesig);
84 	return (c);
85 }
86 
87 /* get a line from the terminal in non-canonical mode */
88 
89 int
90 getaline(char s[], size_t size, int firstchar, BOOL iscaseless)
91 {
92 	int	c, i = 0;
93 	int	j;
94 
95 	/* if a character already has been typed */
96 	if (firstchar != '\0') {
97 		if (iscaseless == YES) {
98 			firstchar = tolower(firstchar);
99 		}
100 		(void) addch((unsigned)firstchar);	/* display it */
101 		s[i++] = firstchar;	/* save it */
102 	}
103 	/* until the end of the line is reached */
104 	while ((c = mygetch()) != '\r' && c != '\n' && c != KEY_ENTER &&
105 	    c != '\003' && c != KEY_BREAK) {
106 		if (c == erasechar() || c == '\b' ||		/* erase */
107 		    c == KEY_BACKSPACE) {
108 			if (i > 0) {
109 				(void) addstr("\b \b");
110 				--i;
111 			}
112 		} else if (c == killchar()) {			/* kill */
113 			for (j = 0; j < i; ++j) {
114 				(void) addch('\b');
115 			}
116 			for (j = 0; j < i; ++j) {
117 				(void) addch(' ');
118 			}
119 			for (j = 0; j < i; ++j) {
120 				(void) addch('\b');
121 			}
122 			i = 0;
123 		} else if (isprint(c) || c == '\t') {		/* printable */
124 			if (iscaseless == YES) {
125 				c = tolower(c);
126 			}
127 			/* if it will fit on the line */
128 			if (i < size) {
129 				(void) addch((unsigned)c);	/* display it */
130 				s[i++] = c;		/* save it */
131 			}
132 		} else if (c == ctrl('X')) {
133 			/* mouse */
134 			(void) getmouseevent(); 	/* ignore it */
135 		} else if (c == EOF) {			/* end-of-file */
136 			break;
137 		}
138 		/* return on an empty line to allow a command to be entered */
139 		if (firstchar != '\0' && i == 0) {
140 			break;
141 		}
142 	}
143 	s[i] = '\0';
144 	return (i);
145 }
146 
147 /* ask user to enter a character after reading the message */
148 
149 void
150 askforchar(void)
151 {
152 	(void) addstr("Type any character to continue: ");
153 	(void) mygetch();
154 }
155 
156 /* ask user to press the RETURN key after reading the message */
157 
158 void
159 askforreturn(void)
160 {
161 	if (linemode == NO) {
162 		(void) fprintf(stderr, "Press the RETURN key to continue: ");
163 		(void) getchar();
164 	}
165 }
166 
167 /* expand the ~ and $ shell meta characters in a path */
168 
169 void
170 shellpath(char *out, int limit, char *in)
171 {
172 	char	*lastchar;
173 	char	*s, *v;
174 
175 	/* skip leading white space */
176 	while (isspace(*in)) {
177 		++in;
178 	}
179 	lastchar = out + limit - 1;
180 
181 	/*
182 	 * a tilde (~) by itself represents $HOME; followed by a name it
183 	 * represents the $LOGDIR of that login name
184 	 */
185 	if (*in == '~') {
186 		*out++ = *in++;	/* copy the ~ because it may not be expanded */
187 
188 		/* get the login name */
189 		s = out;
190 		while (s < lastchar && *in != '/' && *in != '\0' &&
191 		    !isspace(*in)) {
192 			*s++ = *in++;
193 		}
194 		*s = '\0';
195 
196 		/* if the login name is null, then use $HOME */
197 		if (*out == '\0') {
198 			v = getenv("HOME");
199 		} else {	/* get the home directory of the login name */
200 			v = logdir(out);
201 		}
202 		/* copy the directory name */
203 		if (v != NULL) {
204 			(void) strcpy(out - 1, v);
205 			out += strlen(v) - 1;
206 		} else {
207 			/* login not found so ~ must be part of the file name */
208 			out += strlen(out);
209 		}
210 	}
211 	/* get the rest of the path */
212 	while (out < lastchar && *in != '\0' && !isspace(*in)) {
213 
214 		/* look for an environment variable */
215 		if (*in == '$') {
216 			/* copy the $ because it may not be expanded */
217 			*out++ = *in++;
218 
219 			/* get the variable name */
220 			s = out;
221 			while (s < lastchar && *in != '/' && *in != '\0' &&
222 			    !isspace(*in)) {
223 				*s++ = *in++;
224 			}
225 			*s = '\0';
226 
227 			/* get its value */
228 			if ((v = getenv(out)) != NULL) {
229 				(void) strcpy(out - 1, v);
230 				out += strlen(v) - 1;
231 			} else {
232 				/*
233 				 * var not found, so $ must be part of
234 				 * the file name
235 				 */
236 				out += strlen(out);
237 			}
238 		} else {	/* ordinary character */
239 			*out++ = *in++;
240 		}
241 	}
242 	*out = '\0';
243 }
244