1 /* pro_menu.c: Menu subsystem
2 
3    Copyright (c) 1997-2003, Tarik Isani (xhomer@isani.org)
4 
5    This file is part of Xhomer.
6 
7    Xhomer is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License version 2
9    as published by the Free Software Foundation.
10 
11    Xhomer is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Xhomer; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 
22 /* TBD:
23 */
24 
25 #ifdef PRO
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <dirent.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include "pdp11_defs.h"
33 #include "pro_lk201.h"
34 
35 #define MENU_X		24			/* x position of top of menu */
36 #define MENU_Y		2			/* y position of top of menu */
37 
38 #define MENU_BW		4			/* width of menu border */
39 #define MENU_AW		30			/* active width of menu */
40 #define MENU_W		2*MENU_BW+MENU_AW	/* width of menu */
41 
42 #define MENU_BH		2			/* height of menu border */
43 #define MENU_AH		MENU_TOP_NUM		/* active height of menu */
44 #define MENU_H		2*MENU_BH+2+MENU_AH	/* height of menu */
45 
46 #define MENU_PX		(MENU_X+1)
47 #define MENU_PY		(MENU_Y+MENU_BH+2+pro_menu_pos)
48 
49 #define MENU_TOP_NUM	13			/* number of top level menu items */
50 #define MENU_SERIAL_NUM	8			/* number of serial menu items */
51 #define MENU_ABOUT_NUM	13			/* number of about menu items */
52 
53 #define MENU_TOP	0
54 #define MENU_SERIAL	1
55 #define MENU_FILE	2
56 #define MENU_ABOUT	3
57 
58 #define MENU_TOP_RETURN	0
59 #define MENU_TOP_SCREEN	1
60 #define MENU_TOP_RX0	2
61 #define MENU_TOP_RX1	3
62 #define MENU_TOP_RD0	4
63 #define MENU_TOP_COM	5
64 #define MENU_TOP_PTR	6
65 #define MENU_TOP_KB	7
66 #define MENU_TOP_SAVE	8
67 #define MENU_TOP_REST	9
68 #define MENU_TOP_RESET	10
69 #define MENU_TOP_ABOUT	11
70 #define MENU_TOP_SHUT	12
71 
72 #define MENU_MAXENTRIES	1024		/* maximum number of menu entries */
73 #define MENU_MAXFILELEN	255		/* maximum filename length */
74 
75 LOCAL int	pro_menu_last_char;	/* tracks last char, for auto-repeat */
76 LOCAL int	pro_menu_key_ctrl;	/* tracks whether ctrl key is depressed */
77 LOCAL int	pro_menu_on;		/* tracks whether menu is on */
78 LOCAL int	pro_menu_top_start;	/* start item number of item list */
79 LOCAL int	pro_menu_top_pos;	/* menu item selected */
80 LOCAL int	pro_menu_serial_start;	/* start item number of item list */
81 LOCAL int	pro_menu_serial_pos;	/* position of serial menu bar */
82 LOCAL int	pro_menu_file_start;	/* start item number of item list */
83 LOCAL int	pro_menu_file_pos;	/* position of file menu bar */
84 LOCAL int	pro_menu_active;	/* currently active menu */
85 
86 LOCAL int	pro_menu_start;		/* start postion */
87 LOCAL int	pro_menu_pos;		/* current position */
88 LOCAL int	pro_menu_items;		/* number of menu items */
89 
90 LOCAL char	title[MENU_AW+1];
91 LOCAL char	blank[MENU_W+1];
92 LOCAL char	blank_top[MENU_W+1];
93 LOCAL char	blank_bot[MENU_W+1];
94 LOCAL char	item[MENU_MAXENTRIES][MENU_MAXFILELEN+1];
95 LOCAL int	item_ok[MENU_MAXENTRIES];
96 LOCAL char	menu_bar[MENU_W+1];
97 
98 
99 /* Place menu bar on menu */
100 
pro_menu_bar(int pro_menu_pos)101 void pro_menu_bar (int pro_menu_pos)
102 {
103 	pro_overlay_print(MENU_PX, MENU_PY, 1, 1, menu_bar);
104 }
105 
106 
107 /* Concatenate s2 and s3 into s1, limited by length n */
108 
pro_menu_concat(char * s1,char * s2,char * s3,int n)109 void pro_menu_concat (char *s1, char *s2, char *s3, int n)
110 {
111 int	i, pos;
112 
113 
114 	pos = 0;
115 
116 	if (s2 != NULL)
117 	  for(i=0; i<strlen(s2); i++)
118 	  if (pos<n)
119 	    s1[pos++] = s2[i];
120 
121 	if (s3 != NULL)
122 	  for(i=0; i<strlen(s3); i++)
123 	  if (pos<n)
124 	    s1[pos++] = s3[i];
125 
126 	s1[pos] = '\0';
127 }
128 
129 
130 /* Make serial assignments */
131 
pro_menu_assign_serial(int devnum,struct sercall ** dev,int * port)132 void pro_menu_assign_serial (int devnum, struct sercall **dev, int *port)
133 {
134 	switch(devnum)
135 	{
136 	  case 0:
137 	  case 1:
138 	  case 2:
139 	  case 3:
140 	    *dev = &pro_serial;
141 	    *port = devnum;
142 	    break;
143 
144 	  case 4:
145 	    *dev = &pro_digipad;
146 	    *port = 0;
147 	    break;
148 
149 	  case 5:
150 	    *dev = &pro_lk201;
151 	    *port = 0;
152 	    break;
153 
154 	  case 6:
155 	    *dev = &pro_la50;
156 	    *port = 0;
157 	    break;
158 
159 	  case 7:
160 	    *dev = &pro_null;
161 	    *port = 0;
162 	    break;
163 
164 	  default:
165 	    break;
166 	}
167 }
168 
169 
170 /* Return s2 + serial assignment printout in s1 */
171 /* Also return menu item number */
172 
pro_menu_print_serial(char * s1,char * s2,struct sercall * dev,int port)173 int pro_menu_print_serial (char *s1, char *s2, struct sercall *dev, int port)
174 {
175 int	item;
176 char	s3[MENU_AW+1], s4[MENU_AW+1];
177 
178 
179 	item = 0;
180 
181 	if (dev == &pro_serial)
182 	{
183 	  sprintf(s4, "serial%d (", port);
184 	  pro_menu_concat(s3, s4, pro_serial_devname[port], MENU_AW);
185 	  pro_menu_concat(s4, s3, ")", MENU_AW);
186 	  item = port;
187 	}
188 	else if (dev == &pro_digipad)
189 	{
190 	  sprintf(s4, "digipad");
191 	  item = 4;
192 	}
193 	else if (dev == &pro_lk201)
194 	{
195 	  sprintf(s4, "lk201");
196 	  item = 5;
197 	}
198 	else if (dev == &pro_la50)
199 	{
200 	  sprintf(s4, "la50");
201 	  item = 6;
202 	}
203 	else if (dev == &pro_null)
204 	{
205 	  sprintf(s4, "null");
206 	  item = 7;
207 	}
208 
209 	pro_menu_concat(s1, s2, s4, MENU_AW);
210 
211 	return item;
212 }
213 
214 
215 /* Update directory path name */
216 
pro_menu_newdir(char ** dir,char * new)217 void pro_menu_newdir(char **dir, char *new)
218 {
219 int	i, len;
220 char	*temp;
221 
222 
223 	/* Do nothing if current directory is specified */
224 
225 	if (strcmp(new, ".") != 0)
226 	{
227 	  temp = strdup(*dir);
228 
229 	  if (*dir != NULL)
230 	    free(*dir);
231 
232 	  if (strcmp(new, "..") == 0)
233 	  {
234 	    /* Up one level */
235 
236 	    /* Get last directory name
237 	       Remove it if it is not . or ..
238 	       Otherwise, add on a .. */
239 
240 	    len = strlen(temp);
241 
242 	    for(i=len-1; i>0; i--)
243 	    {
244 	      if (temp[i-1] == '/')
245 	        break;
246 	    }
247 
248 	    if ((strcmp(temp+i, "./") == 0) || (strcmp(temp+i, "../") == 0))
249 	    {
250 	      *dir = malloc(len + 4);
251 	      strcpy(*dir, temp);
252 	      strcat(*dir, "../");
253 	    }
254 	    else
255 	    {
256 	      temp[i] = '\0';
257 	      *dir = strdup(temp);
258 	    }
259 	  }
260 	  else
261 	  {
262 	    /* Down one level */
263 
264 	    len = strlen(temp) + strlen(new) + 2;
265 	    *dir = malloc(len);
266 	    strcpy(*dir, temp);
267 	    strcat(*dir, new);
268 	    strcat(*dir, "/");
269 	  }
270 
271 	  free(temp);
272 	}
273 }
274 
275 
276 /* Print menu */
277 
pro_menu_print(int start)278 void pro_menu_print (int start)
279 {
280 int	i;
281 char	itmp[MENU_AW+1];
282 
283 
284 	blank_top[0] = 24;
285 	blank_top[MENU_W-1] = 26;
286 
287 	blank[0] = 31;
288 	blank[MENU_W-1] = 27;
289 
290 	blank_bot[0] = 30;
291 	blank_bot[MENU_W-1] = 28;
292 
293 	for(i=1; i<MENU_W-1; i++)
294 	{
295 	  blank_top[i] = 25;
296 	  blank[i] = 32;
297 	  blank_bot[i] = 29;
298 	}
299 
300 	blank_top[MENU_W] = '\0';
301 	blank[MENU_W] = '\0';
302 	blank_bot[MENU_W] = '\0';
303 
304 	pro_overlay_print(MENU_X, MENU_Y, 0, 1, blank_top);
305 
306 	for(i=1; i<MENU_H-1; i++)
307 	  pro_overlay_print(MENU_X, MENU_Y+i, 0, 1, blank);
308 
309 	pro_overlay_print(MENU_X, MENU_Y+MENU_H-1, 0, 1, blank_bot);
310 
311 	pro_overlay_print(MENU_X+MENU_BW, MENU_Y+MENU_BH, 0, 1, title);
312 
313 	for(i=0; i<MENU_AH; i++)
314 	  if ((i+start)<pro_menu_items)
315 	  {
316 	    pro_menu_concat(itmp, "", item[i+start], MENU_AW);
317 	    pro_overlay_print(MENU_X+MENU_BW, MENU_Y+MENU_BH+2+i, 0, item_ok[i+start], itmp);
318 	  }
319 }
320 
321 
322 /* Initialize and print file menu */
323 
pro_menu_file(char ** filename)324 void pro_menu_file (char **filename)
325 {
326 DIR		*dp;
327 struct dirent	*ep;
328 struct stat	statbuf;
329 int		i, j;
330 char		fname[MENU_MAXFILELEN+1];
331 char		sname[MENU_MAXFILELEN+1];
332 char		strtemp[MENU_MAXFILELEN+1];
333 char		*dir = NULL;
334 
335 
336 	pro_menu_active = MENU_FILE;
337 	pro_menu_items = 1;
338 	pro_menu_file_pos = 0;
339 
340 	if (filename == &pro_rx_file[0])
341 	{
342 	  sprintf(strtemp, "Floppy 0 : ");
343 	  dir = pro_rx_dir[0];
344 	}
345 	else if (filename == &pro_rx_file[1])
346 	{
347 	  sprintf(strtemp, "Floppy 1 : ");
348 	  dir = pro_rx_dir[1];
349 	}
350 	else if (filename == &pro_rd_file)
351 	{
352 	  sprintf(strtemp, "Hard disk 0 : ");
353 	  dir = pro_rd_dir;
354 	}
355 
356 	sprintf(item[0], "  ");
357 
358 	pro_menu_concat(title, strtemp, dir, MENU_AW);
359 
360 	dp = opendir(dir);
361 	if (dp != NULL)
362 	{
363 	  do
364 	  {
365 	    ep = readdir(dp);
366 
367 	    if (ep != NULL)
368 	    {
369 	      pro_menu_concat(fname, "", ep->d_name, MENU_MAXFILELEN);
370 	      pro_menu_concat(sname, dir, ep->d_name, MENU_MAXFILELEN);
371 	      stat(sname, &statbuf);
372 
373 	      /* Check if link or regular file or directory */
374 
375 	      if ((statbuf.st_mode&S_IFMT) == S_IFDIR)
376 	      {
377 	        pro_menu_concat(item[pro_menu_items], "1 ", fname, MENU_MAXFILELEN);
378 	        item_ok[pro_menu_items] = 1;
379 	        pro_menu_items++;
380 	      }
381 	      else if ((statbuf.st_mode&S_IFMT) == S_IFLNK)
382 	      {
383 	        pro_menu_concat(item[pro_menu_items], "2 ", fname, MENU_MAXFILELEN);
384 	        item_ok[pro_menu_items] = 1;
385 	        pro_menu_items++;
386 	      }
387 	      else if ((statbuf.st_mode&S_IFMT) == S_IFREG)
388 	      {
389 	        pro_menu_concat(item[pro_menu_items], "3 ", fname, MENU_MAXFILELEN);
390 	        item_ok[pro_menu_items] = 1;
391 	        pro_menu_items++;
392 	      }
393 	    }
394 	  }
395 	  while ((ep != NULL) && (pro_menu_items < (MENU_MAXENTRIES-1)));
396 
397 	  (void) closedir(dp);
398 
399 	  /* Sort directory */
400 
401 	  for(j=pro_menu_items-1; j>1; j--)
402 	    for(i=pro_menu_items-1; i>1; i--)
403 	    {
404 	      if (strcmp(item[i], item[i-1]) < 0)
405 	      {
406 	        /* swap */
407 
408 	        strcpy(strtemp, item[i-1]);
409 	        strcpy(item[i-1], item[i]);
410 	        strcpy(item[i], strtemp);
411 	      }
412 	    }
413 
414 	  /* Replace first character and search for current name */
415 
416 	  for(i=0; i<pro_menu_items; i++)
417 	  {
418 	    if (strcmp(*filename, item[i]+2) == 0)
419 	      pro_menu_file_pos = i;
420 
421 	    if (item[i][0] == '1')
422 	      item[i][0] = 'D';
423 	    else if (item[i][0] == '2')
424 	      item[i][0] = 'L';
425 	    else if (item[i][0] == '3')
426 	      item[i][0] = ' ';
427 	  }
428 	}
429 	else
430 	  printf("Error: can't open directory\r\n");
431 
432 	if (pro_menu_file_pos>MENU_AH-1)
433 	  pro_menu_file_start = pro_menu_file_pos - MENU_AH + 1;
434 	else
435 	  pro_menu_file_start = 0;
436 
437 	pro_menu_pos = pro_menu_file_pos;
438 	pro_menu_start = pro_menu_file_start;
439 
440 	pro_menu_print(pro_menu_start);
441 	pro_menu_bar(pro_menu_pos-pro_menu_start);
442 }
443 
444 
445 /* Initialize and print serial menu */
446 
pro_menu_serial(struct sercall ** porttype,int port)447 void pro_menu_serial (struct sercall **porttype, int port)
448 {
449 int	i;
450 
451 
452 	for(i=0; i<MENU_SERIAL_NUM; i++)
453 	  item_ok[i] = 1;
454 
455 	pro_menu_serial_pos = pro_menu_print_serial(item[0], "", *porttype, port);
456 	if (pro_menu_serial_pos>(MENU_AH-1))
457 	  pro_menu_serial_start = pro_menu_serial_pos - MENU_AH + 1;
458 	else
459 	  pro_menu_serial_start = 0;
460 
461 	/* Disable in-use ports from selection */
462 
463 	if ((porttype != &pro_com) && (pro_com != &pro_null))
464 	  item_ok[pro_menu_print_serial(item[0], "", pro_com, pro_com_port)] = 0;
465 
466 	if ((porttype != &pro_ptr) && (pro_ptr != &pro_null))
467 	  item_ok[pro_menu_print_serial(item[0], "", pro_ptr, pro_ptr_port)] = 0;
468 
469 	if ((porttype != &pro_kb_orig) && (pro_kb_orig != &pro_null))
470 	  item_ok[pro_menu_print_serial(item[0], "", pro_kb_orig, pro_kb_port)] = 0;
471 
472 	if ((porttype != &pro_la50device) && (pro_la50device != &pro_null))
473 	  item_ok[pro_menu_print_serial(item[0], "", pro_la50device, pro_la50device_port)] = 0;
474 
475 	pro_menu_active = MENU_SERIAL;
476 	pro_menu_start = pro_menu_serial_start;
477 	pro_menu_pos = pro_menu_serial_pos;
478 	pro_menu_items = MENU_SERIAL_NUM;
479 
480 	if (porttype == &pro_com)
481 	  sprintf(title, "Communications Port");
482 	else if (porttype == &pro_ptr)
483 	  sprintf(title, "Printer Port");
484 	else if (porttype == &pro_kb_orig)
485 	  sprintf(title, "Keyboard Port");
486 
487 	pro_menu_print_serial(item[0], "", &pro_serial, 0);
488 	pro_menu_print_serial(item[1], "", &pro_serial, 1);
489 	pro_menu_print_serial(item[2], "", &pro_serial, 2);
490 	pro_menu_print_serial(item[3], "", &pro_serial, 3);
491 	pro_menu_print_serial(item[4], "", &pro_digipad, 0);
492 	pro_menu_print_serial(item[5], "", &pro_lk201, 0);
493 	pro_menu_print_serial(item[6], "", &pro_la50, 0);
494 	pro_menu_print_serial(item[7], "", &pro_null, 0);
495 
496 	pro_menu_print(pro_menu_start);
497 	pro_menu_bar(pro_menu_pos-pro_menu_start);
498 }
499 
500 
501 /* Initialize and print "about XHOMER" page */
502 
pro_menu_about()503 void pro_menu_about ()
504 {
505 int	i;
506 
507 
508 	for(i=0; i<MENU_ABOUT_NUM; i++)
509 	  item_ok[i] = 1;
510 
511 	pro_menu_active = MENU_ABOUT;
512 	pro_menu_start = 0;
513 	pro_menu_pos = MENU_ABOUT_NUM - 1;
514 	pro_menu_items = MENU_ABOUT_NUM;
515 
516 	sprintf(title, "About XHOMER");
517 
518 	sprintf(item[0], "Welcome to  XHOMER, a  Digital");
519 	sprintf(item[1], "Pro/350   machine    emulator,");
520 	sprintf(item[2], "written by  Tarik Isani.  This");
521 	sprintf(item[3], "emulator   is   based   on   a");
522 	sprintf(item[4], "slightly  modified  version of");
523 	sprintf(item[5], "the  PDP-11 CPU core from  the");
524 	sprintf(item[6], "SIMH simulator.  Download from");
525 	sprintf(item[7], "http://xhomer.isani.org/");
526 	sprintf(item[8], " ");
527 	sprintf(item[9], "Please direct any questions or");
528 	sprintf(item[10], "feedback to: xhomer@isani.org");
529 	sprintf(item[11], " ");
530 	sprintf(item[12], "Previous menu");
531 
532 	pro_menu_print(pro_menu_start);
533 	pro_menu_bar(pro_menu_pos-pro_menu_start);
534 }
535 
536 
537 /* Initialize and print top-level menu */
538 
pro_menu_top()539 void pro_menu_top ()
540 {
541 int	i;
542 
543 	for(i=0; i<MENU_AW+2*MENU_BW-2; i++)
544 	  menu_bar[i] = ' ';
545 	menu_bar[i] = '\0';
546 
547 	for(i=0; i<MENU_TOP_NUM; i++)
548 	  item_ok[i] = 1;
549 
550 	item_ok[MENU_TOP_RD0] = 0;
551 	item_ok[MENU_TOP_SAVE] = 0;
552 	item_ok[MENU_TOP_REST] = 0;
553 	item_ok[MENU_TOP_RESET] = 0;
554 
555 	pro_menu_active = MENU_TOP;
556 	pro_menu_start = pro_menu_top_start;
557 	pro_menu_pos = pro_menu_top_pos;
558 	pro_menu_items = MENU_TOP_NUM;
559 	pro_menu_on = 1;
560 	pro_overlay_enable();
561 
562 	sprintf(title, "XHOMER (version %s)", PRO_VERSION);
563 	sprintf(item[0],  "Return to emulator");
564 	sprintf(item[1], "Screen mode : %s", pro_screen_full?"full":"window");
565 	pro_menu_concat(item[2], "rx0 : ", pro_rx_file[0], MENU_AW);
566 	pro_menu_concat(item[3], "rx1 : ", pro_rx_file[1], MENU_AW);
567 	pro_menu_concat(item[4], "rd0 : ", pro_rd_file, MENU_AW);
568 	pro_menu_print_serial(item[5], "com : ", pro_com, pro_com_port);
569 	pro_menu_print_serial(item[6], "ptr : ", pro_ptr, pro_ptr_port);
570 	pro_menu_print_serial(item[7], "kb  : ", pro_kb_orig, pro_kb_port);
571 	sprintf(item[8], "Save configuration");
572 	sprintf(item[9], "Restore defaults and reset");
573 	sprintf(item[10], "Reset");
574 	sprintf(item[11], "About XHOMER");
575 	sprintf(item[12], "Shutdown emulator");
576 
577 	pro_menu_print(pro_menu_start);
578 	pro_menu_bar(pro_menu_pos-pro_menu_start);
579 }
580 
581 
582 /* This routine filters keyboard characters
583    Any characters which are not menu commands are passed through */
584 
pro_menu(int key)585 int pro_menu (int key)
586 {
587 int	retchar, schar, menu_pos_old;
588 
589 	retchar = key;
590 	schar = key;
591 
592 	/* Handle auto-repeat from real LK201 */
593 
594 	if (schar == PRO_LK201_REPEAT)
595 	  schar = pro_menu_last_char;
596 	else
597 	  pro_menu_last_char = schar;
598 
599 	if (schar == PRO_LK201_CTRL)
600 	  pro_menu_key_ctrl = 1;
601 	else if (schar == PRO_LK201_ALLUPS)
602 	  pro_menu_key_ctrl = 0;
603 	else if ((schar == PRO_LK201_DEL) && (pro_menu_key_ctrl == 1))
604 	  pro_exit();
605 	else if (pro_menu_on == 1)
606 	{
607 	  /* Process menu commands */
608 
609 	  menu_pos_old = pro_menu_pos;
610 
611 	  if (schar == PRO_LK201_UP)
612 	  {
613 	    /* Scroll menu bar up */
614 
615 	    if (pro_menu_pos > 0)
616 	    {
617 	      pro_menu_bar(pro_menu_pos-pro_menu_start);
618 
619 	      do
620 	        pro_menu_pos--;
621 	      while ((pro_menu_pos > 0) && (item_ok[pro_menu_pos] == 0));
622 
623 	      if (item_ok[pro_menu_pos] == 0)
624 	        pro_menu_pos = menu_pos_old;
625 
626 	      if (pro_menu_pos<pro_menu_start)
627 	      {
628 	        pro_menu_start = pro_menu_pos;
629 	        pro_menu_print(pro_menu_start);
630 	      }
631 	      pro_menu_bar(pro_menu_pos-pro_menu_start);
632 	    }
633 	    retchar = PRO_NOCHAR;
634 	  }
635 	  else if (schar == PRO_LK201_DOWN)
636 	  {
637 	    /* Scroll menu bar down */
638 
639 	    if (pro_menu_pos < (pro_menu_items-1))
640 	    {
641 	      pro_menu_bar(pro_menu_pos-pro_menu_start);
642 
643 	      do
644 	        pro_menu_pos++;
645 	      while ((pro_menu_pos < (pro_menu_items-1)) && (item_ok[pro_menu_pos] == 0));
646 
647 	      if (item_ok[pro_menu_pos] == 0)
648 	        pro_menu_pos = menu_pos_old;
649 
650 	      if (pro_menu_pos>pro_menu_start+MENU_AH-1)
651 	      {
652 	        pro_menu_start = pro_menu_pos - MENU_AH + 1;
653 	        pro_menu_print(pro_menu_start);
654 	      }
655 	      pro_menu_bar(pro_menu_pos-pro_menu_start);
656 	    }
657 	    retchar = PRO_NOCHAR;
658 	  }
659 	  else if ((schar == PRO_LK201_RETURN) || (schar == PRO_LK201_DO))
660 	  {
661 	    if (pro_menu_active == MENU_TOP)
662 	    {
663 	      /* Execute menu item */
664 
665 	      pro_menu_top_start = pro_menu_start;
666 	      pro_menu_top_pos = pro_menu_pos;
667 
668 	      switch (pro_menu_pos)
669 	      {
670 	        case MENU_TOP_RETURN:
671 	          /* Turn off menu */
672 
673 	          pro_menu_on = 0;
674 	          pro_overlay_disable();
675 	          break;
676 
677 	        case MENU_TOP_SCREEN:
678 	          /* Switch screen mode */
679 
680 	          pro_screen_close();
681 
682 	          if (pro_screen_full == 0)
683 	            pro_screen_full = 1;
684 	          else
685 	            pro_screen_full = 0;
686 
687 	          if (pro_screen_init() == PRO_FAIL)
688 	          {
689 	            /* Switch mode back */
690 
691 	            pro_screen_close();
692 
693 	            if (pro_screen_full == 0)
694 	              pro_screen_full = 1;
695 	            else
696 	              pro_screen_full = 0;
697 
698 	            pro_screen_init();
699 	          }
700 
701 	          pro_menu_top();
702 	          break;
703 
704 	        case MENU_TOP_RX0:
705 	        case MENU_TOP_RX1:
706 	          /* Floppy 0, 1 */
707 
708 	          /* Open floppy door */
709 
710 	          pro_rx_open_door(pro_menu_pos-MENU_TOP_RX0);
711 
712 	          pro_menu_file(&pro_rx_file[pro_menu_pos-MENU_TOP_RX0]);
713 	          break;
714 
715 	        case MENU_TOP_RD0:
716 	          /* Hard disk 0 */
717 
718 	          pro_menu_file(&pro_rd_file);
719 	          break;
720 
721 	        case MENU_TOP_COM:
722 	          /* com menu */
723 
724 	          pro_menu_serial(&pro_com, pro_com_port);
725 	          break;
726 
727 	        case MENU_TOP_PTR:
728 	          /* ptr menu */
729 
730 	          pro_menu_serial(&pro_ptr, pro_ptr_port);
731 	          break;
732 
733 	        case MENU_TOP_KB:
734 	          /* kb menu */
735 
736 	          pro_menu_serial(&pro_kb_orig, pro_kb_port);
737 	          break;
738 
739 		case MENU_TOP_ABOUT:
740 		  pro_menu_about();
741 		  break;
742 
743 	        case MENU_TOP_SHUT:
744 	          pro_exit();
745 	          break;
746 
747 	        default:
748 	          break;
749 	      }
750 	    }
751 	    else if (pro_menu_active == MENU_SERIAL)
752 	    {
753 	      switch (pro_menu_top_pos)
754 	      {
755 	        case MENU_TOP_COM:
756 	          pro_com_exit();
757 		  pro_menu_assign_serial(pro_menu_pos, &pro_com, &pro_com_port);
758 	          pro_com_open();
759 	          break;
760 
761 	        case MENU_TOP_PTR:
762 	          pro_ptr_exit();
763 		  pro_menu_assign_serial(pro_menu_pos, &pro_ptr, &pro_ptr_port);
764 	          pro_ptr_open();
765 	          break;
766 
767 	        case MENU_TOP_KB:
768 	          pro_kb_exit();
769 		  pro_menu_assign_serial(pro_menu_pos, &pro_kb, &pro_kb_port);
770 	          pro_kb_open();
771 	          break;
772 
773 	        default:
774 	          break;
775 	      }
776 
777 	      pro_menu_top();
778 	    }
779 	    else if (pro_menu_active == MENU_FILE)
780 	    {
781 	      switch (pro_menu_top_pos)
782 	      {
783 	        case MENU_TOP_RX0:
784 	        case MENU_TOP_RX1:
785 	          /* Check if directory, file or none */
786 
787 	          if (item[pro_menu_pos][0] == 'D')
788 		  {
789 	            /* Update directory name */
790 
791 	            pro_menu_newdir(&pro_rx_dir[pro_menu_top_pos-MENU_TOP_RX0], item[pro_menu_pos]+2);
792 	            pro_menu_file(&pro_rx_file[pro_menu_top_pos-MENU_TOP_RX0]);
793 	          }
794 	          else
795 	          {
796 	            /* Update file name */
797 
798 	            if (pro_rx_file[pro_menu_top_pos-MENU_TOP_RX0] != NULL)
799 	              free(pro_rx_file[pro_menu_top_pos-MENU_TOP_RX0]);
800 
801 	            pro_rx_file[pro_menu_top_pos-MENU_TOP_RX0] = strdup(item[pro_menu_pos]+2);
802 
803 	            /* Close floppy door */
804 
805 	            /* Check if no image */
806 
807 	            if (pro_menu_pos != 0)
808 	              pro_rx_close_door(pro_menu_top_pos-MENU_TOP_RX0);
809 	            pro_menu_top();
810 	          }
811 	          break;
812 
813 	        case MENU_TOP_RD0:
814 	          pro_menu_top();
815 	          break;
816 
817 	        default:
818 	          break;
819 	      }
820 	    }
821 	    else if (pro_menu_active == MENU_ABOUT)
822 	    {
823 	      if (pro_menu_pos == (MENU_ABOUT_NUM-1))
824 	        pro_menu_top();
825 	    }
826 
827 	    retchar = PRO_NOCHAR;
828 	  }
829 	}
830 	else if ((schar == PRO_LK201_PRINT) && (pro_menu_key_ctrl == 1))
831 	{
832 	  /* Turn on top-level menu */
833 
834 	  pro_menu_top();
835 
836 	  pro_menu_top_start = 0;
837 	  pro_menu_top_pos = 0;
838 
839 	  retchar = PRO_NOCHAR;
840 	}
841 
842 	return retchar;
843 }
844 
845 
846 /* Reset menu subsystem */
847 
pro_menu_reset()848 void pro_menu_reset ()
849 {
850 	pro_menu_last_char = 0;
851 	pro_menu_key_ctrl = 0;
852 	pro_menu_on = 0;
853 }
854 #endif
855