Category : C Source Code
Archive   : CSTUFF.ZIP
Filename : BARMENU.C
found in the "C Power User's Guide". Should compile with two warnings
*/
#include "stdio.h"
#include "dos.h"
#include "stdlib.h"
#define BORDER 1
#define ESC 27
#define MAX_FRAME 10
#define MAX_BAR 1
#define REV_VID 15
#define NRM_VID 112
#define BACKGROUND 0
#define SHADOW 0
#define RETURN 13
#define SPACE ' '
#define UPARROW 72
#define DOWNARROW 80
#define RIGHTARROW 77
#define LEFTARROW 75
#define BCOLOR 112
void bar_save_video(), bar_restore_video(), menu_driver();
void bar_write_string(), write_string(), write_char(), set_vid();
void bar_display_menu(), adjust_choice(), make_menu(), bar_make_menu();
void save_video(), restore_video();
void display_menu(), draw_border();
char far *vid_mem;
char *fruit[] = {
" Apple ",
" Orange ",
" Pear ",
" Grape ",
" Raspberry ",
" Strawberry "
};
char *color[] = {
"Red",
"Yellow",
"Orange",
"Green"
};
char *apple_type[] = {
"Red delicious",
"Jonathan",
"Winesap",
"rOme"
};
char *grape_type[] = {
"Concord",
"cAnadice",
"Thompson",
"Red flame"
};
struct menu_frame
{
int startx, endx, starty, endy;
unsigned char *p;
char **menu;
char *keys;
int border, count;
int active;
int color;
int last_chosen;
} frame [MAX_FRAME];
struct bar_menu_frame
{
int xcoord, ycoord, endx;
int *pos;
unsigned char *p;
char **menu;
char *keys;
int count;
int active;
int color;
} bar [MAX_BAR];
main()
{
set_vid();
textbackground (BACKGROUND);
clrscr ();
make_menu (0, color, "ryog", 4, 5, 1, BORDER, 112);
make_menu (1, apple_type, "rjwo", 4, 7, 4, BORDER, 112);
make_menu (2, grape_type, "catr", 4, 32, 1, BORDER, 112);
bar_make_menu (0, fruit, "aopgrs", 6, 5, 0, 112);
menu_driver ();
}
void set_vid()
{
int vmode;
vmode = video_mode();
if ((vmode != 2) && (vmode != 3) && (vmode != 7))
{
puts ("Video must be in 80 column text mode");
exit (1);
}
if (vmode == 7)
vid_mem = (char far *) 0xB0000000;
else
vid_mem = (char far *) 0xB8000000;
}
void menu_driver()
{
int choice1 = 99, choice2 = 99, choice3 = 99, op = 0, auto_display = 0;
while ((choice1 = bar_pulldown (0, op, &auto_display)) != -1)
{
op = choice2 = 0;
switch (choice1)
{
case 0 : if (auto_display)
{
while ((choice2 != -1) && (op != 77) && (op != 75))
{
op = choice2 = pulldown (0);
if (choice2 == 0)
while ((choice3 != -1) && (op != 77) && (op != 75))
{
op = choice3 = pulldown (1);
restore_video (1);
}
choice3 = 0;
}
restore_video (0);
}
break;
case 1:
case 2: break;
case 3: if (auto_display)
while ((choice2 != -1) && (op != 77) && (op != 75))
{
op = choice2 = pulldown (2);
restore_video (2);
}
break;
case 4:
case 5: break;
}
if (op == -1)
auto_display = 0;
}
bar_restore_video (0);
}
int bar_pulldown (int num, int option, int *auto_display)
{
int choice;
if (!bar [num].active)
{
bar_save_video (num);
bar [num].active = 1;
}
bar_display_menu (num);
return bar_get_resp (num, option, auto_display);
}
void bar_make_menu (int num, char *menu[], char *keys, int count, int x, int y, int color)
{
register int i;
int *pos, *temp, endx;
unsigned char *p;
endx = x;
pos = (int *) malloc (sizeof (int) * count);
temp = pos;
*pos++ = x;
for (i=1; i
endx += strlen (menu [i-1]);
*pos++ = endx;
}
endx += strlen (menu [i]);
pos = temp;
p = (unsigned char *) malloc (endx - x + 1);
if (!p)
{
puts ("Unable to allocate sace for save operation");
exit (0);
}
bar [num].xcoord = x;
bar [num].ycoord = y;
bar [num].pos = pos;
bar [num].p = p;
bar [num].menu = (char **) menu;
bar [num].keys = keys;
bar [num].count = count;
bar [num].active = 0;
bar [num].color = color;
}
void bar_display_menu (int num)
{
register int i;
for (i = 0; i < bar [num].count; i++)
write_string (bar [num].pos [i], bar [num].ycoord, bar [num].menu [i], bar [num].color);
}
int bar_get_resp (int num, int option, int *auto_display)
{
union inkey
{
char ch [2];
int i;
}c;
int y = bar [num].ycoord;
int menu_choice, key_choice;
static int arrow_choice = 0;
switch (option)
{
case RIGHTARROW: arrow_choice++;
break;
case LEFTARROW : arrow_choice--;
break;
}
adjust_choice (&arrow_choice, bar [num].count);
bar_write_string (bar [num].pos [arrow_choice], y, bar [num].menu [arrow_choice], REV_VID);
while (!bioskey (1));
c.i = bioskey (0);
bar_write_string (bar [num].pos [arrow_choice], y, bar [num].menu [arrow_choice], bar [num].color);
if (c.ch [0])
{
if (key_choice = is_in (frame [num].keys, tolower (c.ch [0])))
arrow_choice = key_choice;
else
switch (c.ch [0])
{
case ESC : return -1;
case RETURN : *auto_display = 1;
break;
}
}
else
{
switch (c.ch[1])
{
case RIGHTARROW: arrow_choice++;
break;
case LEFTARROW : arrow_choice--;
break;
case DOWNARROW : *auto_display = 1;
break;
}
}
adjust_choice (&arrow_choice, bar [num].count);
bar_write_string (bar [num].pos [arrow_choice], y, bar [num].menu [arrow_choice], REV_VID);
return arrow_choice;
}
void bar_save_video (int num)
{
register int i;
char *buf_ptr;
char far *v, far *t;
buf_ptr = bar [num].p;
v = vid_mem;
for (i = bar [num].xcoord; i < bar [num].endx + 1; i++)
{
t = (v + (bar [num].ycoord * 160) + i * 2);
*buf_ptr++ = *t++;
*buf_ptr++ = *t;
*(t-1) = ' ';
*t = bar [num].color;
}
}
void bar_restore_video (int num)
{
register int i;
char far *v, far *t;
char *buf_ptr;
buf_ptr = bar [num].p;
v = vid_mem;
t = v;
for (i = bar [num].xcoord; i < bar [num].endx; i++)
{
v = t;
v += (bar [num].ycoord * 160) + i*2;
*v++ = *buf_ptr++;
*v = *buf_ptr++;
}
bar [num].active = 0;
}
void bar_write_string (int x, int y, char *p, int attrib)
{
register int i;
int color;
char far *v;
v = vid_mem;
v += (y * 160) + x * 2;
for (i = x; *p; i++)
{
if (*p == ' ')
color = NRM_VID;
else
color = attrib;
*v++ = *p++;
*v++ = color;
}
}
int pulldown (int num)
{
int choice;
if (!frame [num].active)
{
save_video (num);
frame [num].active = 1;
}
if (frame [num].border)
draw_border (num);
display_menu (num);
return get_resp (num);
}
void make_menu (int num, char *menu[], char *keys, int count, int x, int y, int border, int color)
{
register int i, len;
int endx, endy, choice;
unsigned char *p;
len = 0;
for (i = 0; i < count; i++)
if (strlen (menu [i]) > len)
len = strlen (menu [i]);
endx = len + 3 + x;
endy = count + 1 + y;
p = (unsigned char *) malloc (2 * (endy - y + 1) * (endx - x + 1));
if (!p)
{
puts ("Unable to allocate space for save operation.");
exit (1);
}
frame [num].startx = x;
frame [num].endx = endx;
frame [num].starty = y;
frame [num].endy = endy;
frame [num].p = p;
frame [num].menu = (char **) menu;
frame [num].border = border;
frame [num].keys = keys;
frame [num].count = count;
frame [num].active = 0;
frame [num].color = color;
frame [num].last_chosen = 0;
}
void display_menu (int num)
{
register int i, y;
char **m;
y = frame [num].starty + 1;
m = frame [num].menu;
for (i = 0; i < frame [num].count; i++, y++)
write_string (frame [num].startx + 2, y, m [i], frame [num].color);
}
void draw_border (int num)
{
register int i;
char far *v, far *t;
v = vid_mem;
t = v;
for (i = frame [num].starty + 1; i < frame [num].endy; i++)
{
v += (i * 160) + frame [num].startx * 2;
*v++ = 179;
*v = BCOLOR;
v = t;
v += (i * 160) + frame [num].endx * 2;
*v++ = 179;
*v = BCOLOR;
v = t;
}
for (i = frame [num].startx + 1; i < frame [num].endx; i++)
{
v += (frame [num].starty * 160) + i * 2;
*v++ = 196;
*v = BCOLOR;
v = t;
v += (frame [num].endy * 160) + i * 2;
*v++ = 196;
*v = BCOLOR;
v = t;
}
write_char (frame [num].startx, frame [num].starty, 218, BCOLOR);
write_char (frame [num].startx, frame [num].endy, 192, BCOLOR);
write_char (frame [num].endx, frame [num].starty, 191, BCOLOR);
write_char (frame [num].endx, frame [num].endy, 217, BCOLOR);
}
int get_resp (int num)
{
union inkey {
char ch [2];
int i;
} c;
int key_choice, x = frame [num].startx + 1, y = frame [num].starty + 1;
write_string (x+1, y + frame [num].last_chosen, frame [num].menu [frame [num].last_chosen], REV_VID);
for (;;)
{
while (!bioskey (1));
c.i = bioskey (0);
write_string (x+1, y + frame [num].last_chosen, frame [num].menu [frame [num].last_chosen], frame [num].color);
if (c.ch [0])
{
if (key_choice = is_in (frame [num].keys, tolower (c.ch [0])))
frame [num].last_chosen = key_choice;
switch (c.ch [0])
{
case RETURN: return frame [num].last_chosen;
case SPACE : frame [num].last_chosen++;
break;
case ESC : return -1;
}
}
else
{
switch (c.ch [1])
{
case UPARROW : frame [num].last_chosen--;
break;
case DOWNARROW : frame [num].last_chosen++;
break;
case RIGHTARROW: return RIGHTARROW;
case LEFTARROW : return LEFTARROW;
}
}
adjust_choice (&frame [num].last_chosen, frame [num].count);
write_string (x+1, y + frame [num].last_chosen, frame [num].menu [frame [num].last_chosen], REV_VID);
}
}
void save_video (int num)
{
register int i, j;
char *buf_ptr;
char far *v, far *t;
buf_ptr = frame [num].p;
v = vid_mem;
for (i = frame [num].startx; i < frame [num].endx+1; i++)
for (j = frame [num].starty; j < frame [num].endy+1; j++)
{
t = (v + (j * 160) + i * 2);
*buf_ptr++ = *t++;
*buf_ptr++ = *t;
*(t - 1) = ' ';
*t = frame [num].color;
}
}
void restore_video (int num)
{
register int i, j;
char far *v, far *t;
char *buf_ptr;
buf_ptr = frame [num].p;
v = vid_mem;
t = v;
for (i = frame [num].startx; i < frame [num].endx+1; i++)
for (j = frame [num].starty; j < frame [num].endy+1; j++)
{
v = t;
v += (j * 160) + i * 2;
*v++ = *buf_ptr++;
*v = *buf_ptr++;
}
frame [num].active = 0;
}
int video_mode()
{
union REGS r;
r.h.ah = 15;
return int86 (0x10, &r, &r) & 255;
}
is_in (char *s, char c)
{
register int i;
for (i = 0; *s; i++)
if (*s++ == c)
return i;
return 0;
}
void write_string (int x, int y, char *p, int attrib)
{
register int i;
char far *v;
v = vid_mem;
v += (y * 160) + x * 2;
for (i = x; *p; i++)
{
*v++ = *p++;
*v++ = attrib;
}
}
void write_char (int x, int y, char ch, int attrib)
{
register int i;
char far *v;
v = vid_mem;
v += (y * 160) + x * 2;
*v++ = ch;
*v = attrib;
}
void adjust_choice (int *choice, int count)
{
if (*choice < 0)
*choice = count - 1;
else if (*choice >= count)
*choice = 0;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/