Metropoli BBS
VIEWER: kidsmenu.c MODE: TEXT (ASCII)
/*
 * KIDS MENU
 *
 * Copyright 1993-1995 Dave Dunfield
 *
 * Permission granted for personal (non-commercial) use only.
 *
 * Compile command: cc kmedit -fop
 */
#include <stdio.h>
#include <window.h>

#define	MAXPACK	27

/* Termination codes */
#define	BATCH	50
#define	EXIT	51
#define	BADARG	52

/* Mouse buttons */
#define	MOUSE_LEFT		0x01	/* Select button */
#define	MOUSE_RIGHT		0x02	/* Cancel button */
#define	MOUSE_CENTER	0x04	/* Not used in MICROCAD */

int mousex = 0, mousey = 0, max_icon;
char cursor_flag = 0, video_mode = 3, mouse_flag = -1, quit_flag = -1,
	*ifile = 0, *ofile = 0;

unsigned char itext[MAXPACK][8][6], iattr[MAXPACK][8][6],
	idir[MAXPACK][50], icmd[MAXPACK][50];

char htext[] = {
"KIDS MENU - Copyright 1993-1995 Dave Dunfield, Freely Distributable.\n\n\
Use: KIDSMENU [B=batch_file D=data_file -Lock -Mouse V=video_mode]\n\n\
for Bethany and Michael.\n" };

/*
 * Main program - process commands at the highest level
 */
main(argc, argv)
	int argc;
	char *argv[];
{
	unsigned i, x, y, inkey;
	char *ptr;
	FILE *fp;

	for(i=1; i < argc; ++i) {
		ptr = argv[i];
		switch((toupper(*ptr++) << 8) | toupper(*ptr++)) {
			default:
				printf("Invalid argument: %s\n\n", argv[i]);
			case '?'<<8 :
			case '/?' :
			case '-?' :
				fputs(htext, stdout);
				exit(BADARG);
			case 'V=' :
				video_mode = atoi(ptr);
				break;
			case 'D=' :
				ifile = ptr;
				break;
			case '-M' :
				mouse_flag = 0;
				break;
			case '-L' :
				quit_flag = 0;
				break;
			case 'B=' :
				get_name(icmd, ptr, ".BAT");
				ofile = fopen(icmd, "wvq"); } }


	get_name(icmd, ifile || "KIDSMENU", ".DAT");
	fp = fopen(icmd, "rvqb");

	max_icon = 0;
	do {
		i =  fget(itext[max_icon], sizeof(itext[0]), fp);
		i += fget(iattr[max_icon], sizeof(iattr[0]), fp);
		i += fget(idir [max_icon], sizeof(idir [0]), fp);
		i += fget(icmd [max_icon], sizeof(icmd [0]), fp);
		++max_icon; }
	while(i == (sizeof(itext[0])+sizeof(iattr[0])+sizeof(idir[0])+sizeof(icmd[0])));
	--max_icon;
	fclose(fp);

runmenu:
	set_video_mode(video_mode);
	wopen(0, 0, 80, 25, WCOPEN|WCCLOSE|NORMAL);
	W_OPEN->WINpcurx = W_OPEN->WINpcury = inkey = 0;
	if(mouse_flag = mouse_flag && init_mouse())
		wcursor_block();
	else
		wcursor_off();

	/* Draw the ICONs */
	for(i=x=y=0; i < max_icon; ++i) {
		draw_icon(x, y, itext[i], iattr[i]);
		*W_OPEN = NORMAL;
		wgotoxy(x+3, y+6);
		wprintf("%2u", i+1);
		if((x += 9) > 79) {
			x = 0;
			y += 8; } }

again:
	while(!(mouse_status() & MOUSE_LEFT)) switch(i = wtstc()) {
		case _CEN :
			if(quit_flag) {
				*W_OPEN = NORMAL;
				wclose();
				fputs(htext, stdout);
				exit(EXIT); }
			break;
		case '0' :
		case '1' :
		case '2' :
		case '3' :
		case '4' :
		case '5' :
		case '6' :
		case '7' :
		case '8' :
		case '9' :
			inkey = ((inkey % 10)*10) + (i - '0');
			goto xdraw;
		case _KBS :
			inkey /= 10;
		xdraw:
			if(inkey > max_icon) {
				inkey = 0;
				wputc(7); }
			wgotoxy(76, 24);
			wprintf(inkey ? "%-2u" : "  ", inkey);
			mousex = mousey = -1;
			break;
		case '\n' :
			if(inkey) {
				i = inkey - 1;
				goto runpgm; } }

	if(((mousey % 8) >= 6) || ((mousex % 9) == 8))
		goto again;
	if((i = ((mousey/8)*9) + mousex/9) >= max_icon)
		goto again;

runpgm:	
	*W_OPEN = NORMAL;
	wclose();

	if(ofile) {
		fprintf(ofile,"CD %s\n", idir[i]);
		fprintf(ofile,"%s\n", icmd[i]);
		fclose(ofile);
		exit(BATCH); }

	cd(idir[i]);
	system(icmd[i]);
	goto runmenu;
}

/*
 * Display the ICON
 */
draw_icon(x, y, text, attr)
	unsigned x, y;
	unsigned char text[8][6], attr[8][6];
{
	int x1, y1;

	for(y1=0; y1 < 6; ++y1) {
		wgotoxy(x, y+y1);
		for(x1 = 0; x1 < 8; ++x1) {
			*W_OPEN = attr[x1][y1];
			wputc((unsigned)text[x1][y1] | 0x0100); } }
}

/*
 * Get a filename with extension only if necessary
 */
get_name(dest, name, ext)
	char *dest, *name, *ext;
{
	char c, flag;

	flag = -1;
	while(*dest = c = *name++) {
		++dest;
		if(c == '.')
			flag = 0; }

	if(flag)
		while(*dest++ = *ext++);
}

/*
 * Initializes the mouse driver, returns with -1 if successful.
 */
init_mouse() asm
{
; Initialize & test for mouse
		XOR		AX,AX			; Init functions.
		INT		33h				; Call mouse driver
		AND		AX,AX			; Mouse present
		JZ		initm1			; No, skip it
; Set mouse limits (some drivers do not do it properly on reset)
		XOR		CX,CX			; Lower limit is zero
		MOV		DX,799			; Upper horizontal limit
		MOV		AX,7			; Set horizontal limit
		INT		33h				; Call mouse driver
		MOV		DX,499			; Upper vertical limit
		MOV		AX,8			; Set vertical limit
		INT		33h				; Call mouse driver
		MOV		AX,-1			; Indicate mouse ok
initm1:
}

/*
 * Update mouse position and on-screen cursor. If any button is
 * activated, remove cursor, wait for button to be released, and
 * report it.
 */
mouse_status()
{
	int x, y, z;

	if(!mouse_flag)
		return 0;

	/* Get mouse position and button status */
	asm {
		MOV		AX,0003h	; Mouse status function
		INT		33h			; Call mouse driver
		MOV		-2[BP],BX	; Save buttons
		MOV		-4[BP],DX	; Save Y position
		MOV		-6[BP],CX	; Save X position
		}

	x /= 10;		/* Get new X */
	y /= 20;		/* Get new Y */
	/* If cursor position changed, update cursor and display*/
	if((x != mousex) || (y != mousey))
		wgotoxy(mousex = x, mousey = y);

	/* If any buttons are activated, wait for release, remove cursor */
	if(z & (MOUSE_LEFT|MOUSE_RIGHT|MOUSE_CENTER)) asm
	{
		mloop1:	MOV		AX,0003h		; Mouse status function
				INT		33h				; Call mouse driver
				AND		BL,07h			; Any buttons down?
				JNZ		mloop1			; Wait till clear
	}

	/* Pass back button status to caller */
	return z;
}

/*
 * Set video mode
 */
set_video_mode(x) asm
{
		MOV		AL,4[BP]	; Get mode
		XOR		AH,AH		; Set mode fucntion
		INT		10h			; Call BIOS
}
[ RETURN TO DIRECTORY ]