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