1 /* @(#)graphics3.c 1.4 05/29/84 2 * 3 * Copyright -C- 1982 Barry S. Roitblat 4 * 5 * This file contains additional routines for implementing graphics 6 * primitives for the gremlin picture editor 7 */ 8 9 #include "gremlin.h" 10 #include <sys/types.h> 11 #include <sys/timeb.h> 12 #include <signal.h> 13 #include <sys/time.h> 14 15 /* imports from graphics1.c */ 16 17 extern GRsetwmask(); 18 extern int curx, cury, rmask; 19 extern FILE *display; 20 extern GRClear(); 21 22 /* library routines */ 23 24 extern ftime(); 25 26 GREnableTablet() 27 28 /*--------------------------------------------------------- 29 * This routine enables the graphics tablet. 30 * 31 * Results: None. 32 * 33 * Side Effects: 34 * The tablet cursor is enabled on the AED. This will cause characters 35 * to be sent over the serial line whenever a button on the cursor is 36 * pushed. After calling this routine, the routine GrGetButton may 37 * be called to wait for the next button to be pushed. 38 * 39 * Design: 40 * Note: the AED really messes up with the cursor, because it 41 * continually overwrites CAP with cursor coordinates. Thus the 42 * cursor must disabled before doing ANYTHING to the AED. 43 *--------------------------------------------------------- 44 */ 45 46 { 47 GRsetwmask(127); /* don't write cursor on grid layer */ 48 fputs("3:", display); 49 (void) fflush(display); 50 } 51 52 GRDisableTablet() 53 54 /*--------------------------------------------------------- 55 * This routine disables the graphics tablet so that other things may 56 * be done with the AED. 57 * 58 * Results: None. 59 * Side Effects: The tablet is disabled. 60 *--------------------------------------------------------- 61 */ 62 63 { 64 putc('3', display); 65 putc('\0', display); 66 (void) fflush(display); 67 curx = cury = -1; 68 } 69 70 71 #define MINTIME 100 /* 100 milliseconds */ 72 73 int 74 GRGetButton(stream, px, py) 75 FILE *stream; /* File from which AED chars. can be read */ 76 int *px; /* Address of a word to hold x-coordinate */ 77 int *py; /* Address of word to hold y-coorinate */ 78 79 /*--------------------------------------------------------- 80 * This routine waits for cursor input. 81 * 82 * Results: 83 * The return value is the number of the button that was pushed. 84 * If an error occurs while reading from the stream, -1 is returned. 85 * 86 * Side Effects: 87 * The integers pointed to by px and py are filled in with the 88 * x- and y-coordinates of the cursor at the time the button 89 * was pushed. 90 * 91 * Design: 92 * This is tricky. The AED apparently sends bogus button data at 93 * random times. It can usually be distinguished by the presence 94 * of an illegal button number. We must pick out such data and throw 95 * it away. 96 * 97 * For systems up to 4.1BSD (characterized by the presence of the 98 * SIGTINT signal) the routine waits for cursor input. 99 * For 4.2BSD and beyond, the routine gives an error of -4 if input 100 * is not immediately available (it expects to be called only when 101 * input is available). 102 *--------------------------------------------------------- 103 */ 104 105 { 106 int button; 107 struct timeval selectpoll; 108 static unsigned long time, lastime = 0; 109 struct timeb tp; 110 static char line1[100]; 111 112 selectpoll.tv_sec = 0l; 113 selectpoll.tv_usec = 0l; 114 while (TRUE) 115 { 116 117 #ifndef SIGTINT 118 button = 1 << fileno(stream); 119 if (select(20, &button, 0, 0, &selectpoll) <= 0) return -4; 120 #endif 121 122 if (fgets(line1, 99, stream) == NULL) return -1; 123 if (line1[0] != ':') continue; 124 (void) sscanf(&(line1[1]), "%d", &button); 125 if (fgets(line1, 99, stream) == NULL) return -2; 126 (void) sscanf (line1, "%d", px); 127 if (fgets(line1, 99, stream) == NULL) return -3; 128 (void) sscanf (line1, "%d", py); 129 130 /* wait for minimum duration before accepting */ 131 /* new button to debounce the cursor */ 132 133 ftime(&tp); 134 time = 1000 * tp.time + tp.millitm; 135 if ((time - lastime) < MINTIME ) continue; 136 lastime = time; 137 138 if (button == 2) return 1; 139 if (button == 4) return 2; 140 if (button == 8) return 3; 141 if (button == 1) return 0; 142 } 143 } 144 145 146 147 GRSetGrid(x1, y1, x2, y2, size) 148 int x1, y1, x2, y2, size; 149 /* 150 * This routine sets the grid according to the paramaters 151 * (lower left and upper right corners, and spacing) supplied. The 152 * grid is written to the appropriate memory plane but will not be 153 * displayed unless that plane has been (Read) enabled. 154 */ 155 156 { 157 int i, start; 158 POINT end1, end2; 159 160 GRClear(gridmask); 161 GRsetwmask(gridmask); 162 end1.y = (float) y1; 163 end2.y = (float) y2; 164 start = ((x1 + size - 1) - ((x1 + size - 1) % size)); 165 166 /* start forces the lines to be drawn on pixel 167 boundaries evenly divisible by size */ 168 169 for (i=start; i<=x2; i+=size) 170 { 171 end1.x = end2.x = (float) i; 172 GRVector(&end1, &end2, gridstyle); 173 } /* end for */; 174 end1.x = (float) x1; 175 end2.x = (float) x2; 176 start = ((y1 + size - 1) - ((y1 + size - 1) % size)); 177 for (i=start; i<=y2; i+=size) 178 { 179 end1.y = end2.y = (float) i; 180 GRVector(&end1, &end2, gridstyle); 181 } /* end for */; 182 } /* end SetGrid */; 183 184 185 GRSetRead(mask) 186 int mask; 187 /* 188 * This routine sets the read mask. 189 */ 190 191 { 192 #ifndef FASTIO 193 char s1[3], s2[3], s3[3], s4[3]; 194 #endif 195 196 rmask = mask; 197 198 #ifndef FASTIO 199 GRchex(rmask,s1,2); 200 GRchex(rmask1,s2,2); 201 GRchex(rmask2,s3,2); 202 GRchex(rmask3,s4,2); 203 fprintf(display,"M%s%s%s%s", s1, s2, s3, s4); 204 #else 205 putc('M',display); 206 putc(rmask,display); 207 putc(rmask1,display); 208 putc(rmask2,display); 209 putc(rmask3,display); 210 #endif 211 212 (void) fflush(display); 213 } /* end SetRead */ 214 215 216 GRDisplayGrid() 217 /* 218 * This routine displays the grid created by setgrid by enabling 219 * the appropriate read layer. 220 */ 221 222 { 223 GRSetRead(rmask | gridmask); 224 } /* end DisplayGrid */ 225 226 GRBlankGrid() 227 /* 228 * This routine assures that the grid is not displayed by 229 * setting the read mask to disable the grid layer. 230 */ 231 232 { 233 234 GRSetRead(rmask & ~gridmask); 235 } /* end BlankGrid */ 236 237