1 /* vms/getch.c: input routines for VMS, integrated with smcurses for VMS
2 
3    Copyright (c) 1986-94 Joshua Delahunty, James E. Wilson
4 
5    This software may be copied and distributed for educational, research, and
6    not for profit purposes provided that this copyright and statement are
7    included in all such copies. */
8 
9 #include <iodef.h>
10 #include <ssdef.h>
11 #include <descrip.h>
12 #include <stdio.h>
13 
14 #ifndef TRUE
15 # define TRUE 1
16 # define FALSE 0
17 #endif
18 
19 /* the type of keyboard read we're doing */
20 #define FUNC IO$_TTYREADALL|IO$M_NOECHO|IO$M_TRMNOECHO
21 
22 	static $DESCRIPTOR(chan, "tt:");
23 	static char ungotch;
24 	static unsigned short int kb_chan = 0;	/* channel # */
25 	static unsigned short int	charwaiting = FALSE,
26 					crmode_status = TRUE,
27 					echo_status = FALSE;
28 
29 /* This code was tested and worked on a VAX 11/785 running VMS 5.2.
30    contributed by Ralph Waters, rwaters@jabba.ess.harris.com.  */
31 
32 /* Returns 1 is a character has been pressed, 0 otherwise.  */
kbhit()33 int kbhit()
34 {
35   /* sys$qiow ( [efn] ,chan ,func [,iosb] [,astadr] [,astprm]
36 		[,p1] [,p2] [,p3] [,p4] [,p5] [,p6] )			*/
37 
38   /* The sys$qiow call with the IO$_SENSEMODE|IO$M_TYPEAHDCNT function
39      will return the following in p1:
40 
41      31        24 23        16 15                     0
42      ------------|------------|------------------------
43      | reserved  |   first    | number of characters  |
44      |           | character  | in type-ahead buffer  |
45      |-----------|------------|-----------------------|
46      |                    reserved                    |
47      |                                                |
48      --------------------------------------------------
49   */
50 
51   struct qio_return_type {
52 	 unsigned short int type_ahead_count;	/* type-ahead count */
53 	 unsigned char first_char;		/* first character in buffer */
54 	 unsigned char b_reserved;		/* reserved byte */
55 	 unsigned long int l_reserved; }	/* reserved long word */
56     qio_return;
57 
58   sys$qiow (0, kb_chan, (IO$_SENSEMODE | IO$M_TYPEAHDCNT), 0, 0, 0,
59 	    &qio_return, 0, 0, 0, 0, 0);
60   if (qio_return.type_ahead_count > 0)
61     return(1);
62   else
63     return(0);
64 }
65 
66 /* Another useful function courtesy of Ralph Waters.  */
67 #include <jpidef.h>
68 
69 /* Stores the user's login name in the argument buf.  */
user_name(buf)70 void user_name(buf)
71 char *buf;
72 {
73   /* sys$getjpiw ( [efn], [pidadr], [prcnam], itmlst [,iosb]
74                    [,astadr] [,astprm]					*/
75 
76   long int return_length;
77   struct getjpi_itmlst_type {
78     unsigned short int buffer_length;	/* length of return buffer */
79     unsigned short int item_code;		/* item code to getjpi about */
80     unsigned long int buffer_address;	/* address of return data */
81     unsigned long int return_length_addr; }	/*actual size of return data */
82   getjpi_itmlst;
83 
84   getjpi_itmlst.buffer_length = 12;	/* VMS usernames are 12 chars */
85   getjpi_itmlst.item_code = JPI$_USERNAME;
86   getjpi_itmlst.buffer_address = buf;
87   getjpi_itmlst.return_length_addr = &return_length;
88 
89   sys$getjpiw (0, 0, 0, &getjpi_itmlst, 0, 0, 0);
90 
91   return;
92 }
93 
94 /* After calling this, vms_getch() returns unbuffered single chars.  */
vms_crmode()95 void vms_crmode()	/* Character-Return MODE */
96 {
97 	if(kb_chan == 0)
98 		opengetch();
99 
100 	crmode_status = TRUE;
101 }
102 
103 /* After calling this, vms_getch() returns echoed, buffered characters.  */
vms_nocrmode()104 void vms_nocrmode()	/* NO Character-Return MODE */
105 {
106 	if(kb_chan != 0)
107 		closegetch();
108 
109 	crmode_status = FALSE;
110 }
111 
112 /* Sets up terminal for getch() calls, returns VMS status code.  */
opengetch()113 int opengetch()	/* does the actual assignment work */
114 {
115 	/* assign channel on keyboard */
116 	return(sys$assign(&chan,&kb_chan,0,0));
117 }
118 
119 /* Undoes affects of above, returns VMS status code for the operation.  */
closegetch()120 int closegetch()	/* performs the actual deassignment work */
121 {
122 	int rv;
123 
124 	if(kb_chan != 0) {
125 		/* deassign keyboard channel */
126 		rv = sys$dassgn(kb_chan);
127 		kb_chan = 0;
128 		return(rv);
129 	}
130 }
131 
132 /* Returns an [optionally] unbuffered [non-]echoed input character.
133 
134    If crmode_status is not set, then the code returns one character from
135    the buffered input.
136    If crmode_status is set, then the code returns an `ungot' character if
137    one exists, otherwise it tries to read one unbuffered character from the
138    keyboard.  If echo_status is set, then the character will be echoed
139    before returning.  */
vms_getch()140 char vms_getch()
141 {
142 	int rv;
143 	char kb_buf;				/* buffer for input char */
144 
145 	if(crmode_status) {
146 
147 		if(!charwaiting) {
148 
149 			/* open channel if it hasn't been done already */
150 			if (kb_chan == 0)
151 				opengetch();
152 
153 			/* que an i/o request for a character and wait */
154 			rv = sys$qiow(0,kb_chan,FUNC,0,0,0,&kb_buf,1,0,0,0,0);
155 
156 			/* indicate if something is amiss */
157 			if(rv != SS$_NORMAL) {
158 				printf("?");
159 				exit(rv);
160 			}
161 
162 		} else { /* charwaiting */
163 
164 			kb_buf = ungotch;
165 			charwaiting = FALSE;
166 		}
167 
168 		/* massage for getchar() compatibility */
169 		if (kb_buf == '\r') kb_buf='\n';
170 
171 		/* echo char if we're supposed to */
172 		if (echo_status) putchar(kb_buf);
173 
174 		return(kb_buf);
175 
176 	} else	/* nocrmode */
177 
178 		return(getchar());
179 
180 }
181