Home | History | Annotate | Download | only in cscope-fast
      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