/*--------------------------------------------------------------------------*/
/* File name:	BAR.C							Revision date:	1997.09.25	*/
/* Revised by:	Ulf Ronald Andersson			Revision start:	1997.09.25	*/
/*--------------------------------------------------------------------------*/


#include <aes.h>
#include <vdi.h>
#include <tos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define	TA_LEFT		0
#define	TA_CENTER	1
#define	TA_RIGHT	2
#define	TA_BASE		0
#define	TA_HALF		1

#define  FALSE            0
#define  TRUE             1
#define  SWM_LAUNCH       1

/*	#define  BUTTONWIDTH      68 */
/*	#define  BUTTONHEIGHT     52 */
#define	BUTTONWIDTH		butt_w
#define	BUTTONHEIGHT	butt_h

#define  MAXBUTTONS       64
#define  MAXLINE          256
#define  TOPLEFT          0
#define  TOPRIGHT         1
#define  BOTLEFT          2
#define  BOTRIGHT         3
#define  CNTRL_Q          0x11

#define  MIN(a,b)         (((a) < (b)) ? (a) : (b))
#define  MAX(a,b)         (((a) > (b)) ? (a) : (b))

extern  GEMPARBLK _GemParBlk;
void	init_menu(void);
extern	OBJECT	BAR_menu_1[14];
int		BAR_menu_f;

int   open_v_workst (void), parse_file (char name[], int flag);
int   rc_intersect (GRECT *rect_1, GRECT *rect_2);
void  draw_button (int address, int shift), do_button (int which, int keybd);
void  reload_inf (void), redraw (GRECT *dirty, int which);
void  close_v_workst (void), my_strcpy (char dest[], char src[]);

long	single_Pexec(char *fname_p,char *cline_p, char *eline_p);
void	exit_application(void);
int		init_application(void);

int    work_in[11], work_out[57], handle, win_handle, max_fonts, size, color;
int    full_x, full_y, full_w, full_h, b_hor, b_ver, orient = 123;
char   cmdlines[MAXBUTTONS][MAXLINE];
char   modes[3][16] = { "\x01TOS Single", "\x64MagiC Parallel", "\x65MagiC Single"  };
GRECT  wrk;

int		cell_w, cell_h;
int		butt_w, butt_h;
int		line_0_offs, line_1_offs;
char	own_path[128], cmd_tail[128];
char	*temp_p;

/*--------------------------------------------------------------------------*/

int  open_v_workst()

{
   int  cnt, phys_handle;

   if (appl_init() != -1) {
        for (cnt = 1; cnt < 10; work_in[cnt++] = 1);
        work_in[10] = 2;
        phys_handle = graf_handle (&cnt, &cnt, &cnt, &cnt);
        work_in[0]  = handle = phys_handle;

        v_opnvwk (work_in, &handle, work_out);
        max_fonts = work_out[10];
        if (vq_gdos())
             max_fonts += vst_load_fonts (handle, 0);
        vst_alignment (handle, TA_CENTER, TA_BASE, &cnt, &cnt);
        return (0);
      }
     else
        return (1);
 }

/*--------------------------------------------------------------------------*/

void  close_v_workst()

{
   v_clsvwk (handle);
   appl_exit();
 }

/*--------------------------------------------------------------------------*/

void  draw_button (address, shift)

int  address, shift;

{
   int    n_x, n_y, c_x, c_y, pts[6], col_fg, col_bg;
   char   text[20];
   GRECT  rec;

   col_fg = (color) ? BLACK : WHITE;
   col_bg = (color) ? WHITE : BLACK;
   vswr_mode (handle, MD_REPLACE);

   n_x = address % b_hor;	n_y = address / b_hor;
   wind_get (win_handle, WF_WORKXYWH, &rec.g_x, &rec.g_y, &rec.g_w, &rec.g_h);

   pts[0] = rec.g_x + n_x * BUTTONWIDTH;   pts[1] = rec.g_y + n_y * BUTTONHEIGHT;
   pts[2] = pts[0] + BUTTONWIDTH - 1;      pts[3] = pts[1] + BUTTONHEIGHT - 1;
   vsf_color (handle, col_bg);
   v_bar (handle, pts);

   pts[0]          = rec.g_x + (n_x + 1) * BUTTONWIDTH - 2;
   pts[2] = pts[4] = rec.g_x +  n_x      * BUTTONWIDTH + 1;
   pts[5] = (pts[3] = ++pts[1]) + BUTTONHEIGHT - 2;
   vsl_color (handle, shift ? col_fg : col_bg);
   v_pline (handle, 3, pts);
   pts[0]++;    pts[1]++;    pts[2] = pts[0];    pts[3] = pts[5];    pts[4]++;
   vsl_color (handle, shift ? col_bg : col_fg);
   v_pline (handle, 3, pts);

   vswr_mode (handle, MD_TRANS);
   vst_color (handle, col_fg);
   c_x = rec.g_x + n_x *  BUTTONWIDTH +  BUTTONWIDTH / 2 + (shift ? 2 : 0);
   c_y = rec.g_y + n_y * BUTTONHEIGHT + BUTTONHEIGHT / 2 + (shift ? 2 : 0) + cell_h/2 - 2;
   strcpy (text, &cmdlines[address][2]);
   if (strchr (text, ' ')) {
        v_gtext (handle, c_x, c_y + line_0_offs, strtok (text, " "));
        v_gtext (handle, c_x, c_y + line_1_offs, strtok (NULL, " "));
      }
     else
        v_gtext (handle, c_x, c_y, text);
 }

/*--------------------------------------------------------------------------*/

int  rc_intersect (rect_1, rect_2)

GRECT  *rect_1, *rect_2;

{
   int  cut_x, cut_y, cut_w, cut_h;

   cut_x = MAX (rect_1->g_x, rect_2->g_x);
   cut_y = MAX (rect_1->g_y, rect_2->g_y);
   cut_w = MIN (rect_1->g_x + rect_1->g_w, rect_2->g_x + rect_2->g_w);
   cut_h = MIN (rect_1->g_y + rect_1->g_h, rect_2->g_y + rect_2->g_h);
   rect_2->g_x = cut_x;   rect_2->g_w = cut_w - cut_x;
   rect_2->g_y = cut_y;   rect_2->g_h = cut_h - cut_y;

   return ((cut_w > cut_x) && (cut_h > cut_y));
 }

/*--------------------------------------------------------------------------*/

void  redraw (dirty, which)

GRECT  *dirty;
int    which;

{
   GRECT  rec;
   int    pts[4], cnt;

   graf_mouse (M_OFF, NULL);
   wind_update (BEG_UPDATE);

   wind_get (win_handle, WF_FIRSTXYWH, &rec.g_x, &rec.g_y, &rec.g_w, &rec.g_h);

   while (rec.g_w && rec.g_h) {
        if (rc_intersect (dirty, &rec)) {
             pts[0] = rec.g_x;   pts[2] = rec.g_x + rec.g_w - 1;
             pts[1] = rec.g_y;   pts[3] = rec.g_y + rec.g_h - 1;
             vs_clip (handle, 1, pts);
             for (cnt = 0; cnt <= b_hor * b_ver; cnt++)
                  draw_button (cnt, cnt == which);
             vs_clip (handle, 0, pts);
           }
        wind_get (win_handle, WF_NEXTXYWH, &rec.g_x, &rec.g_y, &rec.g_w, &rec.g_h);
      }

   wind_update (END_UPDATE);
   graf_mouse (M_ON, NULL);
 }

/*--------------------------------------------------------------------------*/

void  reload_inf()

{
   char  path[200], name[64];
   int   button;

   path[0] = 'A' + Dgetdrv();   path[1] = ':';
   Dgetpath (&path[2], 0);
   if (path[3] == '\0')   path[2] = '\0';
   strcat (path, "\\*.INF");

   fsel_exinput (path, name, &button, "Choose Info File");
   if (button == 0)   return;

   if (strrchr (path, '\\'))
        strcpy (strrchr (path, '\\') + 1, name);
     else
        strcat (path, name);

   if (parse_file (path, 1))  return;

   switch (orient) {
      case TOPLEFT :
        wind_set (win_handle, WF_CURRXYWH, 3, full_y + 3,
                        b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
        break;
      case TOPRIGHT:
        wind_set (win_handle, WF_CURRXYWH, full_w - b_hor * BUTTONWIDTH - 4, full_y + 3,
                        b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
        break;
      case BOTLEFT:
        wind_set (win_handle, WF_CURRXYWH, 3, full_h + full_y - b_ver * BUTTONHEIGHT - 6,
                        b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
        break;
      case BOTRIGHT:
        wind_set (win_handle, WF_CURRXYWH, full_w - b_hor * BUTTONWIDTH - 4, full_h + full_y -
                        b_ver * BUTTONHEIGHT - 6, b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
      }

   wind_get (win_handle, WF_WORKXYWH, &wrk.g_x, &wrk.g_y, &wrk.g_w, &wrk.g_h);
   redraw (&wrk, -1);
 }

/*--------------------------------------------------------------------------*/

void  do_button (which, keybd)

int  which, keybd;

{
   int    mouse;
   char   alert[160], path[24], cmds[24];
   GRECT  rec;

   if (cmdlines[which][0] == 255) {
        wind_set(win_handle,WF_TOP);
        return;
      }

   rec.g_x = wrk.g_x + (which % b_hor) * (rec.g_w = BUTTONWIDTH);
   rec.g_y = wrk.g_y + (which / b_hor) * (rec.g_h = BUTTONHEIGHT);
   redraw (&rec, which);
   wind_update (BEG_MCTRL);
   evnt_button (1, 1, 0, &mouse, &mouse, &mouse, &mouse);
   wind_update (END_MCTRL);
   redraw (&rec, -1);

   if (keybd == 0) {
        if (cmdlines[which][0] == 254)
             form_alert (1, "[0][Button Bar| |\xbd 1996 Version 0.2|  Sander RM SToks,"
                            " Peter Rottengatter   ][ Okay ]");
          else {
             strcpy (alert, &cmdlines[which][18]);
             if (alert[1] == ':') {
                  Dsetdrv (alert[0] - 'A');
                  strcpy (alert, &cmdlines[which][20]);
                }
             if (strrchr (alert, '\\'))
                  *strrchr (alert, '\\') = '\0';
			Dsetpath (alert);
			if (_GemParBlk.global[1] != 1)
				shel_write (SWM_LAUNCH, cmdlines[which][0], modes[cmdlines[which][1]][0],
							&cmdlines[which][18], &cmdlines[which][127]);
			else
				single_Pexec(&cmdlines[which][18], &cmdlines[which][127],NULL);
           }
      }
     else {
        if (cmdlines[which][0] == 254)
             reload_inf();
          else {
             if (strlen (&cmdlines[which][18]) > 22) {
                  strncpy (path, &cmdlines[which][18], 3);   strcpy (path + 3, "...");
                  strcat (path, &cmdlines[which][2+strlen(&cmdlines[which][18])]);
                }
               else
                  strcpy (path, &cmdlines[which][18]);

             if (strlen (&cmdlines[which][128]) > 22) {
                  strncpy (path, &cmdlines[which][128], 19);   strcpy (path + 19, "...");
                }
               else
                  strcpy (cmds, &cmdlines[which][128]);

             sprintf (alert, "[0][%s :| | Path : %s| Cmds : %s| Mode : %s][ Okay ]",
                       &cmdlines[which][2], path, cmds, &modes[cmdlines[which][1]][1]);
             form_alert (1, alert);
           }
      }
 }

/*--------------------------------------------------------------------------*/

void  my_strcpy (destination, source)

char  destination[], source[];

{
   if (source != NULL)
        strcpy (destination, source);
     else
        strcpy (destination, "");
 }

/*--------------------------------------------------------------------------*/

int  parse_file (name, flag)

char  name[];
int   flag;

{	FILE  *bar;
	char  line[256], text[100], font[33], *ptr;
	char  format[] = "ButtonBar: Parse error in line %d\n";
	int   cnt, index, l_num = 0;

	if (orient == 123) {
        b_hor = 2;   b_ver = 10;
        orient = 1;
        for (cnt = 0; cnt < MAXBUTTONS; cnt++) {
             cmdlines[cnt][0] = 255;   cmdlines[cnt][2] = '\0';
           }
      }

   if ((bar = fopen (name, "r")) == NULL) {
        if (flag) {
             if (strlen (name) < 8)
                  fprintf (stderr, "ButtonBar: Couldn't open .INF file\n");
               else
                  form_alert (1, "[3][ButtonBar :| |Couldn't open .INF file ! ][ Too Bad ]");
           }
        return (-1);
      }

   do {
        ptr = fgets (line, 255, bar);
        l_num++;
     } while (line[0] == '#' && ptr != NULL);
   if (ptr == NULL) {
        fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
      }
   sscanf (line, "%i,%i,%s\n", &b_hor, &b_ver, text);
   if (b_hor * b_ver > MAXBUTTONS)   b_ver = MAXBUTTONS / b_hor;

   if (! strncmp (text, "topleft", 7))
        orient = TOPLEFT;
     else if (! strncmp (text, "topright", 8))
        orient = TOPRIGHT;
     else if (! strncmp (text, "botleft", 7))
        orient = BOTLEFT;
     else if (! strncmp (text, "botright", 8))
        orient = BOTRIGHT;
     else {
        fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
      }

   do {
        ptr = fgets (line, 255, bar);
        l_num++;
     } while (line[0] == '#' && ptr != NULL);
   if (ptr == NULL) {
        fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
      }
   index = strlen(line) - 1;
   if (line[index] == '\n')   line[index] = '\0';
   color = atoi (line);
   if (strchr (line, ',') == NULL) {
        fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
      }
   strcpy (line, strchr (line, ',') + 1);
   size = atoi (line);
   if (strchr (line, ',') == NULL) {
        fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
      }
   strcpy (line, strchr (line, ',') + 1);
   for (cnt = 1; cnt <= max_fonts; cnt++) {
        index = vqt_name (handle, cnt, font);
        if (strcmp (font, line) == 0)
             break;
      }
   if (cnt > max_fonts)
        index = vqt_name (handle, 1, font);
   vst_font (handle, index);
   vst_point (handle, size, &cnt, &cnt, &cell_w, &cell_h);

	butt_w = (cell_w * 17)/2;
	butt_h = (cell_h * 5)/2;
	line_1_offs = cell_h/2;
	line_0_offs = line_1_offs-cell_h;
  
   for (cnt = 0; cnt < MAXBUTTONS; cnt++) {
        do {
             ptr = fgets (line, 255, bar);
             l_num++;
          } while (line[0] == '#' && ptr != NULL);
        if (ptr == NULL)
             break;
        index = strlen(line) - 1;
        if (line[index] == '\n')   line[index] = '\0';
        cmdlines[cnt][0] = atoi (line);
        if (strchr (line, ',') == NULL) {
             fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
           }
        strcpy (line, strchr (line, ',') + 1);
        cmdlines[cnt][1] = atoi (line);
        if (strchr (line, ',') == NULL) {
             fprintf (stderr, format, l_num);   fclose (bar);   return (-2);
           }
        my_strcpy (&cmdlines[cnt][2], strtok (strchr (line, ',') + 1, ","));
        my_strcpy (&cmdlines[cnt][18], strtok (NULL, ","));
        my_strcpy (&cmdlines[cnt][128], strtok (NULL, ","));
        cmdlines[cnt][127] = strlen (&cmdlines[cnt][128]);
      }

   fclose (bar);

   cmdlines[b_hor * b_ver - 1][0] = 254;
   strcpy (&cmdlines[b_hor * b_ver - 1][2], "About");

   return (0);
 }

/*--------------------------------------------------------------------------*/

int main()

{	int  mesag[8], m_x, m_y, btn, kbd, scan, clks, ev_which, quit = FALSE;

	if (init_application())
	{	fprintf (stderr, "ButtonBar: Couldn't open Virtual Workstation\n");
		return (-1);
	}
	while (! quit)
	{	ev_which = evnt_multi (MU_KEYBD | MU_BUTTON | MU_MESAG, 1, 1, 1, 0, 0, 0, 0, 0,
			0, 0, 0, 0, 0, mesag, 0, 0, &m_x, &m_y, &btn, &kbd, &scan, &clks);
		if (ev_which & MU_MESAG)
			switch (mesag[0])
			{
			case WM_REDRAW :
				redraw ((GRECT *) &mesag[4], -1);
				break;
			case WM_TOPPED :
				wind_set (win_handle, WF_TOP);
				break;
			}
		if (ev_which & MU_BUTTON)
		{	if (m_x > wrk.g_x && m_x < wrk.g_x+wrk.g_w && m_y > wrk.g_y && m_y < wrk.g_y+wrk.g_h)
				do_button (b_hor * ((m_y - wrk.g_y) / BUTTONHEIGHT)
							+ (m_x - wrk.g_x) / BUTTONWIDTH, kbd);
			else
				Bconout (2,7);   /* Ping! */
		}
		if (ev_which & MU_KEYBD)
			if ((scan & 0xff) == CNTRL_Q)   quit = TRUE;
	}

	exit_application();
	return (0);
}	/* ends main */

/*--------------------------------------------------------------------------*/

long	single_Pexec(char *fname_p,char *cline_p,char *eline_p)
{	long	result;
	exit_application();
	result = Pexec(0, fname_p, cline_p, eline_p);
	init_application();
	return( result );
}	/* ends single_Pexec */
/*--------------------------------------------------------------------------*/

void	exit_application(void)
{
	menu_bar(BAR_menu_1,FALSE);
	wind_new();
	close_v_workst();
}	/* ends exit_application */

/*--------------------------------------------------------------------------*/

int		init_application(void)
{
	if	(open_v_workst())
		return (1);
	wind_get (0, WF_WORKXYWH, &full_x, &full_y, &full_w, &full_h);

	shel_read(own_path,cmd_tail);
	temp_p = strrchr(own_path, '\\');
	if	(temp_p != NULL)
		temp_p++;
	else
		temp_p = own_path;
	strcpy(temp_p,"BAR.INF");
	if (parse_file (own_path, 0))
		if (parse_file ("\\BAR.INF", 1))   return (-3);

	if ((win_handle = wind_create (0, full_w - b_hor*BUTTONWIDTH, full_y, b_hor * BUTTONWIDTH,
						b_ver * BUTTONHEIGHT + 2)) < 0)
	{	fprintf (stderr, "ButtonBar: Couldn't create window\n");
		return (-4);
	}

	switch (orient)
	{
	case TOPLEFT:
		wind_open (win_handle, 3, full_y + 3, b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
		break;
	case TOPRIGHT:
		wind_open (win_handle, full_w - b_hor * BUTTONWIDTH - 4, full_y + 3, b_hor * BUTTONWIDTH,
						b_ver * BUTTONHEIGHT + 2);
		break;
	case BOTLEFT:
		wind_open (win_handle, 3, full_h + full_y - b_ver * BUTTONHEIGHT - 6, b_hor * BUTTONWIDTH,
						b_ver * BUTTONHEIGHT + 2);
		break;
	case BOTRIGHT:
		wind_open (win_handle, full_w - b_hor * BUTTONWIDTH - 4, full_h + full_y - 
						b_ver * BUTTONHEIGHT - 6, b_hor * BUTTONWIDTH, b_ver * BUTTONHEIGHT + 2);
	}

	wind_set (win_handle, WF_BEVENT, 1, 0, 0, 0);
	wind_get (win_handle, WF_WORKXYWH, &wrk.g_x, &wrk.g_y, &wrk.g_w, &wrk.g_h);
	redraw (&wrk, -1);
	graf_mouse (ARROW, 0L);
	init_menu();
	menu_bar(BAR_menu_1,TRUE);
	return (0);
}	/* ends init_application */

/*--------------------------------------------------------------------------*/
/* End of file:	BAR.C														*/
/*--------------------------------------------------------------------------*/
