File: common\slideshw.c
1 /***********************************************************************/
2 /* These routines are called by getakey to allow keystrokes to control */
3 /* Fractint to be read from a file. */
4 /***********************************************************************/
5
6 #include <ctype.h>
7 #include <time.h>
8 #include <string.h>
9 #ifndef XFRACT
10 #include <conio.h>
11 #endif
12
13 /* see Fractint.c for a description of the "include" hierarchy */
14 #include "port.h"
15 #include "prototyp.h"
16
17 static void sleep_secs(int);
18 static int showtempmsg_txt(int,int,int,int,char *);
19 static void message(int secs, char far *buf);
20 static void slideshowerr(char far *msg);
21 static int get_scancode(char *mn);
22 static void get_mnemonic(int code, char *mnemonic);
23
24 static FCODE s_ENTER [] = "ENTER" ;
25 static FCODE s_INSERT [] = "INSERT" ;
26 static FCODE s_DELETE [] = "DELETE" ;
27 static FCODE s_ESC [] = "ESC" ;
28 static FCODE s_TAB [] = "TAB" ;
29 static FCODE s_PAGEUP [] = "PAGEUP" ;
30 static FCODE s_PAGEDOWN [] = "PAGEDOWN" ;
31 static FCODE s_HOME [] = "HOME" ;
32 static FCODE s_END [] = "END" ;
33 static FCODE s_LEFT [] = "LEFT" ;
34 static FCODE s_RIGHT [] = "RIGHT" ;
35 static FCODE s_UP [] = "UP" ;
36 static FCODE s_DOWN [] = "DOWN" ;
37 static FCODE s_F1 [] = "F1" ;
38 static FCODE s_CTRL_RIGHT[] = "CTRL_RIGHT";
39 static FCODE s_CTRL_LEFT [] = "CTRL_LEFT" ;
40 static FCODE s_CTRL_DOWN [] = "CTRL_DOWN" ;
41 static FCODE s_CTRL_UP [] = "CTRL_UP" ;
42 static FCODE s_CTRL_END [] = "CTRL_END" ;
43 static FCODE s_CTRL_HOME [] = "CTRL_HOME" ;
44
45 #define MAX_MNEMONIC 20 /* max size of any mnemonic string */
46
47 struct scancodes
48 {
49 int code;
50 FCODE *mnemonic;
51 };
52
53 static struct scancodes far scancodes[] =
54 {
55 { ENTER, s_ENTER },
56 { INSERT, s_INSERT },
57 { DELETE, s_DELETE },
58 { ESC, s_ESC },
59 { TAB, s_TAB },
60 { PAGE_UP, s_PAGEUP },
61 { PAGE_DOWN, s_PAGEDOWN },
62 { HOME, s_HOME },
63 { END, s_END },
64 { LEFT_ARROW, s_LEFT },
65 { RIGHT_ARROW, s_RIGHT },
66 { UP_ARROW, s_UP },
67 { DOWN_ARROW, s_DOWN },
68 { F1, s_F1 },
69 { RIGHT_ARROW_2, s_CTRL_RIGHT},
70 { LEFT_ARROW_2, s_CTRL_LEFT },
71 { DOWN_ARROW_2, s_CTRL_DOWN },
72 { UP_ARROW_2, s_CTRL_UP },
73 { CTL_END, s_CTRL_END },
74 { CTL_HOME, s_CTRL_HOME },
75 { -1, NULL }
76 };
77 #define stop sizeof(scancodes)/sizeof(struct scancodes)-1
78
79 static int get_scancode(char *mn)
80 {
81 int i;
82 i = 0;
83 for(i=0;i< stop;i++)
84 if(far_strcmp((char far *)mn,scancodes[i].mnemonic)==0)
85 break;
86 return(scancodes[i].code);
87 }
88
89 static void get_mnemonic(int code,char *mnemonic)
90 {
91 int i;
92 i = 0;
93 *mnemonic = 0;
94 for(i=0;i< stop;i++)
95 if(code == scancodes[i].code)
96 {
97 far_strcpy(mnemonic,scancodes[i].mnemonic);
98 break;
99 }
100 }
101 #undef stop
102
103 char busy = 0;
104 static FILE *fpss = NULL;
105 static long starttick;
106 static long ticks;
107 static int slowcount;
108 static unsigned int quotes;
109 static char calcwait = 0;
110 static int repeats = 0;
111 static int last1 = 0;
112 static FCODE smsg[] = "MESSAGE";
113 static FCODE sgoto[] = "GOTO";
114 static FCODE scalcwait[] = "CALCWAIT";
115 static FCODE swait[] = "WAIT";
116
117 /* places a temporary message on the screen in text mode */
118 static int showtempmsg_txt(int row, int col, int attr,int secs,char *txt)
119 {
120 int savescrn[80];
121 int i;
122 if(text_type > 1)
123 return(1);
124 for(i=0;i<80;i++)
125 {
126 movecursor(row,i);
127 savescrn[i] = get_a_char();
128 }
129 putstring(row,col,attr,txt);
130 movecursor(25,80);
131 sleep_secs(secs);
132 for(i=0;i<80;i++)
133 {
134 movecursor(row,i);
135 put_a_char(savescrn[i]);
136 }
137 return(0);
138 }
139
140 static void message(int secs, char far *buf)
141 {
142 int i;
143 char nearbuf[41];
144 i = -1;
145 while(buf[++i] && i< 40)
146 nearbuf[i] = buf[i];
147 nearbuf[i] = 0;
148 if(text_type < 2)
149 showtempmsg_txt(0,0,7,secs,nearbuf);
150 else if (showtempmsg(nearbuf) == 0)
151 {
152 sleep_secs(secs);
153 cleartempmsg();
154 }
155 }
156
157 /* this routine reads the file autoname and returns keystrokes */
158 int slideshw()
159 {
160 int out,err,i;
161 char buffer[81];
162 if(calcwait)
163 {
164 if(calc_status == 1 || busy) /* restart timer - process not done */
165 return(0); /* wait for calc to finish before reading more keystrokes */
166 calcwait = 0;
167 }
168 if(fpss==NULL) /* open files first time through */
169 if(startslideshow()==0)
170 {
171 stopslideshow();
172 return (0);
173 }
174
175 if(ticks) /* if waiting, see if waited long enough */
176 {
177 if(clock_ticks() - starttick < ticks) /* haven't waited long enough */
178 return(0);
179 ticks = 0;
180 }
181 if (++slowcount <= 18)
182 {
183 starttick = clock_ticks();
184 ticks = CLK_TCK/5; /* a slight delay so keystrokes are visible */
185 if (slowcount > 10)
186 ticks /= 2;
187 }
188 if(repeats>0)
189 {
190 repeats--;
191 return(last1);
192 }
193 start:
194 if(quotes) /* reading a quoted string */
195 {
196 if((out=fgetc(fpss)) != '\"' && out != EOF)
197 return(last1 = out);
198 quotes = 0;
199 }
200 /* skip white space: */
201 while ((out=fgetc(fpss)) == ' ' || out == '\t' || out == '\n') { }
202 switch(out)
203 {
204 case EOF:
205 stopslideshow();
206 return(0);
207 case '\"': /* begin quoted string */
208 quotes = 1;
209 goto start;
210 case ';': /* comment from here to end of line, skip it */
211 while((out=fgetc(fpss)) != '\n' && out != EOF) { }
212 goto start;
213 case '*':
214 if (fscanf(fpss,"%d",&repeats) != 1
215 || repeats <= 1 || repeats >= 256 || feof(fpss))
216 {
217 static FCODE msg[] = "error in * argument";
218 slideshowerr(msg);
219 last1 = repeats = 0;
220 }
221 repeats -= 2;
222 return(out = last1);
223 }
224
225 i = 0;
226 for(;;) /* get a token */
227 {
228 if(i < 80)
229 buffer[i++] = (char)out;
230 if((out=fgetc(fpss)) == ' ' || out == '\t' || out == '\n' || out == EOF)
231 break;
232 }
233 buffer[i] = 0;
234 if(buffer[i-1] == ':')
235 goto start;
236 out = -12345;
237 if(isdigit(buffer[0])) /* an arbitrary scan code number - use it */
238 out=atoi(buffer);
239 else if(far_strcmp((char far *)buffer,smsg)==0)
240 {
241 int secs;
242 out = 0;
243 if (fscanf(fpss,"%d",&secs) != 1)
244 {
245 static FCODE msg[] = "MESSAGE needs argument";
246 slideshowerr(msg);
247 }
248 else
249 {
250 int len;
251 char buf[41];
252 buf[40] = 0;
253 fgets(buf,40,fpss);
254 len = strlen(buf);
255 buf[len-1]=0; /* zap newline */
256 message(secs,(char far *)buf);
257 }
258 out = 0;
259 }
260 else if(far_strcmp((char far *)buffer,sgoto)==0)
261 {
262 if (fscanf(fpss,"%s",buffer) != 1)
263 {
264 static FCODE msg[] = "GOTO needs target";
265 slideshowerr(msg);
266 out = 0;
267 }
268 else
269 {
270 char buffer1[80];
271 rewind(fpss);
272 strcat(buffer,":");
273 do
274 {
275 err = fscanf(fpss,"%s",buffer1);
276 } while( err == 1 && strcmp(buffer1,buffer) != 0);
277 if(feof(fpss))
278 {
279 static FCODE msg[] = "GOTO target not found";
280 slideshowerr(msg);
281 return(0);
282 }
283 goto start;
284 }
285 }
286 else if((i = get_scancode(buffer)) > 0)
287 out = i;
288 else if(far_strcmp(swait,(char far *)buffer)==0)
289 {
290 float fticks;
291 err = fscanf(fpss,"%f",&fticks); /* how many ticks to wait */
292 fticks *= CLK_TCK; /* convert from seconds to ticks */
293 if(err==1)
294 {
295 ticks = (long)fticks;
296 starttick = clock_ticks(); /* start timing */
297 }
298 else
299 {
300 static FCODE msg[] = "WAIT needs argument";
301 slideshowerr(msg);
302 }
303 slowcount = out = 0;
304 }
305 else if(far_strcmp(scalcwait,(char far *)buffer)==0) /* wait for calc to finish */
306 {
307 calcwait = 1;
308 slowcount = out = 0;
309 }
310 else if((i=check_vidmode_keyname(buffer)) != 0)
311 out = i;
312 if(out == -12345)
313 {
314 char msg[MSGLEN];
315 sprintf(msg,s_cantunderstand,buffer);
316 slideshowerr(msg);
317 out = 0;
318 }
319 return(last1 = out);
320 }
321
322 int
323 startslideshow()
324 {
325 if((fpss=fopen(autoname,"r"))==NULL)
326 slides = 0;
327 ticks = 0;
328 quotes = 0;
329 calcwait = 0;
330 slowcount = 0;
331 return(slides);
332 }
333
334 void stopslideshow()
335 {
336 if(fpss)
337 fclose(fpss);
338 fpss = NULL;
339 slides = 0;
340 }
341
342 void recordshw(int key)
343 {
344 char mn[MAX_MNEMONIC];
345 float dt;
346 dt = (float)ticks; /* save time of last call */
347 ticks=clock_ticks(); /* current time */
348 if(fpss==NULL)
349 if((fpss=fopen(autoname,"w"))==NULL)
350 return;
351 dt = ticks-dt;
352 dt /= CLK_TCK; /* dt now in seconds */
353 if(dt > .5) /* don't bother with less than half a second */
354 {
355 if(quotes) /* close quotes first */
356 {
357 quotes=0;
358 fprintf(fpss,"\"\n");
359 }
360 fprintf(fpss,"WAIT %4.1f\n",dt);
361 }
362 if(key >= 32 && key < 128)
363 {
364 if(!quotes)
365 {
366 quotes=1;
367 fputc('\"',fpss);
368 }
369 fputc(key,fpss);
370 }
371 else
372 {
373 if(quotes) /* not an ASCII character - turn off quotes */
374 {
375 fprintf(fpss,"\"\n");
376 quotes=0;
377 }
378 get_mnemonic(key,mn);
379 if(*mn)
380 fprintf(fpss,"%s",mn);
381 else if (check_vidmode_key(0,key) >= 0)
382 {
383 char buf[10];
384 vidmode_keyname(key,buf);
385 fprintf(fpss,buf);
386 }
387 else /* not ASCII and not FN key */
388 fprintf(fpss,"%4d",key);
389 fputc('\n',fpss);
390 }
391 }
392
393 /* suspend process # of seconds */
394 static void sleep_secs(int secs)
395 {
396 long stop;
397 stop = clock_ticks() + (long)secs*CLK_TCK;
398 while(clock_ticks() < stop && kbhit() == 0) { } /* bailout if key hit */
399 }
400
401 static void slideshowerr(char far *msg)
402 {
403 char msgbuf[300];
404 static FCODE errhdg[] = "Slideshow error:\n";
405 stopslideshow();
406 far_strcpy(msgbuf,errhdg);
407 far_strcat(msgbuf,msg);
408 stopmsg(0,msgbuf);
409 }
410