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