/*
  File : asm.c

 Funtions: int display_text(int start, int stop)
           int asm_wprintf(char *fmt, ...)
           void init_interp()
           int interp()
           int quit_proc()
           int d_popup_menu(int msg, DIALOG *d, int c)
           int gfx_mode()
           void printhelp()
           int main()

 This file is a replacement for the files command.c and aim.c
 and cmdwind.c used in the Acorn Archimedes source code.

 Erwin Waterlander, Jul 1997, 2007

*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>

#include <allegro.h>
#include "asm.h"
#include "parse.h"
#include "errors.h"
#include "image.h"
#include "plotutil.h"
#include "commnd.h"
#include "asmdat.h"
#include "imagwind.h"
#define ALT_SW || *argv[i]=='/'


/* ----------- Global variables ---------------- */

char gfx_specs[256];
char mouse_specs[256];

char text_window[ASM_COMMANDS][ASM_COMMAND_LENGTH];  /* cyclic text lines buffer */
int  text_line = 0;                                  /* the current line nr. */
int  text_line_start = 0,display_start=0;   /* start display text from this nr. */
int  text_line_stop  = 0,display_stop=0;    /* stop display text at this nr. */
char text_full  = 0;

int max_col=0, max_signals, number_of_signals;
int prompt_flag = FALSE ;
int current_signal = -1;     /* The actual signal drawn to screen */
char    signal_dir[1024] ,   /* holds directory path where signal are stored
                                and read from */
        macro_dir[1024]  ,   /* not used (yet) */
        help_file[1024]  ,   /* not used (yet) */
        log_file[1024]   ;
int x_res=1024, y_res=768 ;          /* screen resolution */

VENSTER* vp[MAXSIG];
unsigned short MAX_LENGTH=65535;     /*Maximale lengte van een record */
unsigned short SAMPLE_RATE=1024;     /* Default sample-rate  *10         */
BOOL don,bon;                        /* display on, bargraph on */
char asm_run_ini = 1;                /* run ASM_INI_FILE */
FILE *logfile;

RGB asm_gui_fg_color = { 40, 40, 40 };
RGB   asm_gui_bg_color = {  5,  5,  5 };
RGB   asm_emph_color   = { 60,  0,  0 };
RGB   asm_red_color    = { 60,  0,  0 };
RGB   asm_black_color  = {  0,  0,  0 };
RGB   asm_gray_color   = { 15, 15, 15 };
RGB   asm_green_color  = {  0, 40,  0 };
RGB   asm_blue_color   = {  0,  0, 40 };

RGB asm_pallete[256];
int asm_font_width = 8 ;

extern BITMAP *asm_draw_bitmap;     /* defined in plotutil.c */

/**************************************************************************
 *
 * display_text(int start, int stop)
 *
 * Display text from the textbuffer 'text_window' on the screen
 * starting at index 'start' stopping after index 'stop'.
 *
 **************************************************************************/

int display_text(int start, int stop)
{
   int i,j;

   /* you don't need to do this, but on some platforms (eg. Windows) things
    * will be drawn more quickly if you always acquire the screen before
    * trying to draw onto it.
    */
   acquire_screen();

   /* clear the textwindow  */
   rectfill(screen, ASM_TEXT_OFFSET, SCREEN_H-((ASM_TEXT_WINDOW_LINES+1)*text_height(font)), SCREEN_W-2, SCREEN_H-1*text_height(font),
       gui_bg_color);

   if (start <= stop)
   {
      for(i=0; (i+start) <= stop;i++)
         textout_ex(screen, font, text_window[i+start], ASM_TEXT_OFFSET, SCREEN_H-((ASM_TEXT_WINDOW_LINES+1-i)*text_height(font)) ,
            ASM_FG_COLOR, 0);
   }
   else
   {
      for(i=0; (i+start) < ASM_COMMANDS;i++)
         textout_ex(screen, font, text_window[i+start], ASM_TEXT_OFFSET, SCREEN_H-((ASM_TEXT_WINDOW_LINES+1-i)*text_height(font)) ,
            ASM_FG_COLOR, 0);
      j=i;
      for(i=0; i <= stop;i++)
         textout_ex(screen, font, text_window[i], ASM_TEXT_OFFSET, SCREEN_H-((ASM_TEXT_WINDOW_LINES+1-i-j)*text_height(font)) ,
            ASM_FG_COLOR, 0);
   };

   /* you must always release bitmaps before calling any input functions */
   release_screen();

   return 0;
}

/*************************************************************************
 *
 * int asm_wprintf(char *fmt, ...)
 *
 * With the asm_wprintf function text can be printed to the screen.
 * It can be used on a similar way as the standard printf function.
 * The function can only print strings on one line
 * (not multiple '\n' characters)
 * The string is added to the cyclic stringbuffer text_window
 *
 **************************************************************************/

int asm_wprintf(char *fmt, ...)
{
   char buf[ASM_COMMAND_LENGTH];  /* temporarial buffer */

   va_list args;   /* points to each unnamed arg in turn */
   va_start(args, fmt);

   vsprintf(buf,fmt,args);
   strcpy(text_window[text_line],buf);
   va_end(args);

   if(logfile)
      fprintf(logfile,"%s\n",buf);  /* print also to logfile */

   if ( text_full || (text_line > (ASM_TEXT_WINDOW_LINES-1)))
      text_line_start++;

   /* around the circle */
   if ( text_line_start >= ASM_COMMANDS)
      text_line_start = 0;

   display_start = text_line_start;
   display_stop  = text_line;

   /* print the text on the screen in the text_window */
   display_text(text_line_start,text_line);

   text_line++;

   if ( text_line >= ASM_COMMANDS)
   {
      text_line = 0;
      text_full = 1;   /* text_window buffer is full */
   }

   return 0;
}

/*************************************************************************
 *
 * print_error(int error)
 * Each funtion which is called by the CLI returns an
 * error number.
 *
 *************************************************************************/

void print_error(int error)

{
   static char    *error_messages[] = {
      "",                                        /* NO_ERROR */
      "Illegal parameter(s).",                   /* ERR_PARAM */
      "Unable to allocate memory.",              /* ERR_ALLOC */
      "Operation cannot work on complex image.", /* ERR_COMPLEX */
      "Input not a complex-signal.",             /* ERR_NO_COMPLEX */
      "Inputfile is not an ASM or TCL file.",    /* ERR_FILETYPE*/
      "Cannot open file.",                       /* ERR_OPENFILE */
      "Cannot close file.",                      /* ERR_CLOSEFILE */
      "Cannot read file.",          /* ERR_READFILE */
      "Cannot write file.",         /* ERR_WRITEFILE */
      "Cannot access printer.",     /* ERR_PRINTER */
      "No printer installed.",      /* ERR_NO_PRINTER_INSTALL */
      "Queue too small.",           /* ERR_QUEUE */
      "Unknown command.",           /* ERR_UNKNOWN      */
      "Ambiguous command.",         /* ERR_AMBIGUOUS    */
      "Illegal transformation. ",   /* ERR_TRANSFORM    */
      "No shell given.",            /* ERR_NOSHELL      */
      "Could not start shell.",     /* ERR_EXEC         */
      "Command aborted.",           /* ERR_ABORT        */
      "Signal not declared.",       /* ERR_DECL         */
      "Too many displaywindows.",   /* ERR_WINDOWS      */
      "Input does not exist.",      /* ERR_SIGNAL       */
      "Wrong domain or domains do not match.",  /* ERR_DOMAIN   */
      "No imaginary part present.",             /* ERR_NO_IMAG  */
      "No real part present.",                  /* ERR_NO_REAL  */
      "Signal too long.",                       /* ERR_LONG     */
      "Signals have different size.",           /* ERR_SIZE     */
      "Not implemented on complex data.",       /* ERR_IMPL     */
      "Signal already exists."                  /* ERR_EXIST    */
   };

   if (error == 0) return;

   if ((error <= ERR_EXIST) && (error > 0))
   {
      if (error != ERR_EXIST)
         printw("Error: %s\n", error_messages[error]);
      else
         printw("%s\n", error_messages[error]);
      return;
   }
   printw("Unknown error %d\n", error);
}

/************************************************************************
 *
 * void init_interp(void)
 * Display the textwindow
 *
 ************************************************************************/

void init_interp()
{
   FILE *inifile;
   int c;
   char buf[ASM_COMMAND_LENGTH];  /* temporarial buffer */

   sprintf(buf,"<F1> = HELP");
   textout_ex(screen, font, buf, SCREEN_W/4, 0, ASM_FG_COLOR, 0);

   /* draw a line around the textwindow */
   rect(screen, 0, SCREEN_H-((ASM_TEXT_WINDOW_LINES+1)*text_height(font))-1, SCREEN_W-1, SCREEN_H-1, gui_fg_color);
   display_text(text_line_start,text_line);

   /* clear the commandline  */
   rectfill(screen, 0, SCREEN_H-1*text_height(font), SCREEN_W, SCREEN_H, gui_bg_color);

   /* place the prompt on the command line */

   sprintf(buf,"%s", ASM_COMMAND_PROMPT);
   textout_ex(screen, font, buf, ASM_TEXT_OFFSET, SCREEN_H-1*text_height(font) , ASM_GREEN_COLOR, 0);

   /* place cursor on the commandline */
   c = '_';
   sprintf(buf,"%c", c);
   textout_ex(screen, font, buf, ASM_TEXT_OFFSET+text_length(font,ASM_COMMAND_PROMPT), SCREEN_H-1*text_height(font) , ASM_FG_COLOR, 0);

   /* Run ASM_INI_FILE
      The ASM_INI_FILE is a normal macro file */
   if  (asm_run_ini && ((inifile = fopen(ASM_INI_FILE,"r")) != NULL) )
   {
      fclose(inifile);
      asm_run_ini = 0;
      MacroCi(ASM_INI_FILE);
   }

}

void scroll_right(int *blit_x) {
   if ((asm_draw_bitmap != NULL) &&
       ((asm_draw_bitmap->w) > SCREEN_W) &&
       (*blit_x < ( asm_draw_bitmap->w - SCREEN_W/3 ))
       )
   {
      *blit_x += SCREEN_W/3;
      plot_x_offset(vp[current_signal], *blit_x);
   }
}

void scroll_left(int *blit_x) {
   if ((asm_draw_bitmap != NULL) &&
       ((asm_draw_bitmap->w) > SCREEN_W) &&
       (*blit_x > 0 )
       )
   {
      *blit_x -= SCREEN_W/3;
      if (*blit_x < 0)
         *blit_x = 0;
      plot_x_offset(vp[current_signal], *blit_x);
   }
}

void previous_signal(int *blit_x) {
   char buf[ASM_COMMAND_LENGTH];     /* temporarial buffer */
   if((number_of_signals > 0)&&(current_signal>0)&&don)
   {
      *blit_x = 0;
      current_signal--;
      make_plot(vp[current_signal]);
      if(vp[current_signal])
      {
      sprintf(buf,"Signal %s   %d/%d              ",DataSignalName(vp[current_signal]), current_signal+1,number_of_signals);
      textout_ex(screen,font,buf, 2*SCREEN_W/3, 0, gui_fg_color, 0);
      }
   }
}

void next_signal(int *blit_x) {
   char buf[ASM_COMMAND_LENGTH];     /* temporarial buffer */
   if((number_of_signals > 0)&&(current_signal<(number_of_signals-1))&&don)
   {
      *blit_x = 0;
      current_signal++;
      make_plot(vp[current_signal]);
      if(vp[current_signal])
      {
          sprintf(buf,"Signal %s   %d/%d              ",DataSignalName(vp[current_signal]), current_signal+1,number_of_signals);
          textout_ex(screen,font,buf, 2*SCREEN_W/3, 0, gui_fg_color, 0);
      }
   }
}

void zoom_out(int *blit_x) {
   if((current_signal>=0)&&don)
   {
      Window_HScale(vp[current_signal]) = 0.8 * Window_HScale(vp[current_signal]);
      int new_width = Window_HScale(vp[current_signal])*DataLength(vp[current_signal]) + LEFT_XOFFS + RIGHT_XOFFS;
      if ((asm_draw_bitmap != NULL) &&
          (new_width > SCREEN_W) &&
          (*blit_x > 0 )
          )
      {
         make_bitmap(vp[current_signal]);
         if (*blit_x > ( asm_draw_bitmap->w - SCREEN_W/3 )) {
            *blit_x = asm_draw_bitmap->w - SCREEN_W/3;
         }
         if (*blit_x < 0)
            *blit_x = 0;
         plot_x_offset(vp[current_signal], *blit_x);
      } else {
         *blit_x = 0;
         make_plot(vp[current_signal]);
      }
   }
}

void zoom_in(int *blit_x) {
   if((current_signal>=0)&&don)
   {
      Window_HScale(vp[current_signal]) = Window_HScale(vp[current_signal])/0.8;
      int new_width = Window_HScale(vp[current_signal])*DataLength(vp[current_signal]) + LEFT_XOFFS + RIGHT_XOFFS;
      if ((asm_draw_bitmap != NULL) &&
          (new_width > SCREEN_W) &&
          (*blit_x > 0 )
          )
      {
         make_bitmap(vp[current_signal]);
         plot_x_offset(vp[current_signal], *blit_x);
      } else {
         *blit_x = 0;
         make_plot(vp[current_signal]);
      }
   }
}

/************************************************************************
 *
 * int interp()
 *
 * - Capture all the keys that are pressed and build a command.
 *   the command is parsed to funtions in parse.c
 * - Capture Function keys.
 *
 ************************************************************************/

int interp()
{
   int c, c_org, k = 0,  i = 0, error, j;
   int blit_x=0;
   char *cmd, *nxt, *cmmnt;
   char command[ASM_COMMAND_LENGTH]; /* holds the command */
   char buf[ASM_COMMAND_LENGTH];     /* temporarial buffer */

   show_mouse(NULL);      /* no mouse */
   clear(screen);

   strcpy(command,"");    /* clear command */

   init_interp();

   /* Draw current signal, if we come back from the title screen. */
   if (current_signal >= 0 && don) {
      make_plot(vp[current_signal]);
      if(vp[current_signal])
      {
          sprintf(buf,"Signal %s   %d/%d              ",DataSignalName(vp[current_signal]), current_signal+1,number_of_signals);
          textout_ex(screen,font,buf, 2*SCREEN_W/3, 0, gui_fg_color, 0);
      }
   }

   do {

         k = readkey();      /* Capture key */
         c = c_org = k & 0xFF;
         k >>= 8;

         switch(k)
         {

         case KEY_F1:

            asm_wprintf("?                        = list all commands");
            asm_wprintf("<command> ?              = enter parameters interactive");
            asm_wprintf("<Esc>, <Alt>-X, <Ctrl>-C = quit to title screen");
            asm_wprintf("<F1>                     = help");
            asm_wprintf("<F2>, <Left>             = scroll image left");
            asm_wprintf("<F3>, <Right>            = scroll image right");
            asm_wprintf("<F4>, <Shift>-<Left>     = display previous signal");
            asm_wprintf("<F5>, <Shift>-<Right>    = display next signal");
            asm_wprintf("<Ctrl>-<Left>            = zoom out");
            asm_wprintf("<Ctrl>-<Right>           = zoom in");
            asm_wprintf("<Up> ,<PgUp>             = scroll text up");
            asm_wprintf("<Dwn>,<PgDn>             = scroll text down");
            asm_wprintf("All text output is logged in file %s",ASM_LOG_FILE);

            break;

         case KEY_F2:  /* scroll image left */
            scroll_left(&blit_x);
            break;

         case KEY_LEFT:

            if (key_shifts & KB_SHIFT_FLAG) {
               previous_signal(&blit_x);
            } else if (key_shifts & KB_CTRL_FLAG) {
               zoom_out(&blit_x);
            } else {
               scroll_left(&blit_x);
            }

            break;

         case KEY_F3:  /* scroll image right */
            scroll_right(&blit_x);
            break;

         case KEY_RIGHT:

            if (key_shifts & KB_SHIFT_FLAG) {
               next_signal(&blit_x);
            } else if (key_shifts & KB_CTRL_FLAG) {
               zoom_in(&blit_x);
            } else {
               scroll_right(&blit_x);
            }
            break;

         case KEY_F4:    /* display previous signal */
            previous_signal(&blit_x);
            break;

         case KEY_F5:   /* display next signal */

            next_signal(&blit_x);

            break;

         case KEY_UP:
         case KEY_PGUP:      /* scroll text up */


            if (text_full==0)
               if (text_line > (ASM_TEXT_WINDOW_LINES-1))
               {
                  if(display_start>0)
                  {
                     display_start--;
                     display_stop--;
                  }
               }


            if (text_full ==1)
               if ( (display_start) != text_line)
               {
                  display_start--;
                  display_stop--;
               }


            if (display_start < 0)
               display_start = ASM_COMMANDS-1;
            if (display_stop < 0)
               display_stop = ASM_COMMANDS-1;

            display_text(display_start,display_stop);

            break;

         case KEY_DOWN:
         case KEY_PGDN:    /* scroll text down */

            if (text_full==0)
               if ( display_stop < (text_line-1) )
               {
                  display_start++;
                  display_stop++;
               }


            if (text_full ==1)
               if ( ((display_stop) != (text_line-1))
                   && !((display_stop == (ASM_COMMANDS-1)) && (text_line == 0))
                   )
               {
                  display_start++;
                  display_stop++;
               }


            if (display_start >= ASM_COMMANDS)
               display_start = 0;
            if (display_stop >= ASM_COMMANDS)
               display_stop = 0;

            display_text(display_start,display_stop);


            break;

         case KEY_BACKSPACE:
         case KEY_DEL:         /* delete previous character */

            c = ' ';
            sprintf(buf,"%c", c);
            textout_ex(screen, font, buf, ASM_TEXT_OFFSET+(i+strlen(ASM_COMMAND_PROMPT))*asm_font_width, SCREEN_H-1*text_height(font)
                , ASM_FG_COLOR, 0);

            if( i > 0 )
               i-- ;

            c = '_';
            sprintf(buf,"%c", c);
            textout_ex(screen, font, buf, ASM_TEXT_OFFSET+(i+strlen(ASM_COMMAND_PROMPT))*asm_font_width, SCREEN_H-1*text_height(font)
                , ASM_FG_COLOR, 0);

            break;

         case KEY_ENTER:       /* start parsing the command */

            blit_x = 0;       /* reset image scrolling */
            command[i] = '\0';

            asm_wprintf("%s<", command); /* print the command */

            /* clear the commandline, ASM is working  */
            rectfill(screen, 0, SCREEN_H-1*text_height(font), SCREEN_W, SCREEN_H, gui_bg_color);

            i = 0;

            cmd = command;

            /* skip comment ('*--------') from parsing by making it 0 */

            if ((cmmnt = strchr(command, '*')) != NULL) *cmmnt = '\0';
            nxt = nxtarg(&cmd, NULL);
            switch (j = stablk(nxt, 0))
            {
            case -1:
               error = ERR_UNKNOWN;
               break;
            case -2:
               error = ERR_AMBIGUOUS;
               break;
            default:
               nxt = stpblk(cmd);
               if (*nxt == '?')
                  if (*stpblk(nxt + 1) == 0) prompt_flag = TRUE;
               error = cmd_exec(j, cmd);   /* execute the command */
               prompt_flag = FALSE;
               break;
            }
            print_error(error);   /* print return value */

            /* clear the commandline  */
            /* poll_loop function might have left something behind */
            rectfill(screen, 0, SCREEN_H-1*text_height(font), SCREEN_W, SCREEN_H, gui_bg_color);

            /* place the prompt on the command line */

            sprintf(buf,"%s", ASM_COMMAND_PROMPT);
            textout_ex(screen, font, buf, ASM_TEXT_OFFSET, SCREEN_H-1*text_height(font) , ASM_GREEN_COLOR, 0);

            /* place cursor on the commandline */
            c = '_';
            sprintf(buf,"%c", c);
            textout_ex(screen, font, buf, ASM_TEXT_OFFSET+asm_font_width*strlen(ASM_COMMAND_PROMPT), SCREEN_H-1*text_height(font) , ASM_FG_COLOR, 0);

            if(vp[current_signal])
            {
               sprintf(buf,"Signal %s   %d/%d              ",DataSignalName(vp[current_signal]), current_signal+1,number_of_signals);
                textout_ex(screen,font,buf, 2*SCREEN_W/3, 0, gui_fg_color, 0);
            }
            break;

         default:        /* capture characters and catenate to command */

            if ((c < ' ') || (c >= ' '+FONT_SIZE) || (i > (ASM_COMMAND_LENGTH-2)) )
               c = ' ';
            else
            {
               command[i] = (char)c;
               sprintf(buf,"%c",c);
               textout_ex(screen, font,buf,ASM_TEXT_OFFSET+(i+strlen(ASM_COMMAND_PROMPT))*asm_font_width, SCREEN_H-1*text_height(font)
                   , ASM_FG_COLOR, 0);

               if (i < (ASM_COMMAND_LENGTH -2))
                  i++;
               else i = ASM_COMMAND_LENGTH -1;

               c = '_';                 /* print the cursor */
               sprintf(buf,"%c",c);
               textout_ex(screen, font,buf,ASM_TEXT_OFFSET+(i+strlen(ASM_COMMAND_PROMPT))*asm_font_width, SCREEN_H-1*text_height(font)
                   , ASM_FG_COLOR, 0);
            }
            break;
         }

    /* quit if <Esc> or Alt-x or Ctrl-c is pressed */
   } while ( k != KEY_ESC && !(k == KEY_X && c_org == 0) && c_org != 3);

   do {
   } while (mouse_b);

   show_mouse(screen);
   return D_REDRAW;
}

/*************************************************************************
 *
 *
 *
 *************************************************************************/

void config(void)
{
   int i;

   max_signals = MAXSIG;


   number_of_signals = 0;  /* Het aantal momentele signalen in gebruik */
   don = 1;                /* display on */
   bon = 0;                /* bargraph off */

   strcpy(signal_dir,".\\");


      if ((i=init_cmds()) !=1)
      {
        asm_wprintf("init=%d\n",i);
      }
}

/*************************************************************************
 *
 *
 *
 *************************************************************************/

int quit_proc()
{
   return D_CLOSE;
}

MENU menu[] =
{
   { "&Go",                      interp,           NULL },
   { "&Quit",                    quit_proc,        NULL },
   { NULL,                       NULL,             NULL }
};

int d_popup_menu(int msg, DIALOG *d, int c)
{
   int x;
      if (msg == MSG_CLICK)
   {
     x = do_menu(d->dp ,mouse_x, mouse_y);
     if ( x == 1 )
      return D_CLOSE;
     else
      return D_REDRAW;
      }
   else
   return D_O_K;
}

DIALOG title_screen[] =
{
   /* (dialog proc)     (x)   (y)   (w)   (h)           (fg)  (bg)  (key) (flags)  (d1)  (d2)  (dp) */
   { d_clear_proc,      0,    0,    0,    0,              0,   0,    0,    0,       0,    0,    NULL },
   { d_menu_proc,       0,    0,    0,    0,              0,   0,    0,    0,       0,    0,    menu },
   { d_ctext_proc,    400,  168,    0,    0,  ASM_RED_COLOR,   0,    0,    0,       0,    0,    "ASM, Another Signal Manager" },
   { d_ctext_proc,    400,   200,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    ASM_VERSION },
   { d_ctext_proc,    400,   232,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    "Original version by Erwin Waterlander and Edwin Zoer, 1993" },
   { d_ctext_proc,    400,   264,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    "Ported to DOS by Erwin Waterlander, 1997" },
   { d_ctext_proc,    400,   280,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    "Ported to Windows and Linux by Erwin Waterlander, 2007" },
   { d_ctext_proc,    400,   296,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    "" },
   { d_ctext_proc,    400,   312,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    "" },
   { d_ctext_proc,    400,   328,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    gfx_specs },
   { d_ctext_proc,    400,   360,   0,    0,   ASM_FG_COLOR,   0,    0,    0,       0,    0,    mouse_specs },
   { d_ctext_proc,    400,   392,   0,    0, ASM_GREEN_COLOR,   0,    0,    0,       0,    0,    "Press <Enter> to begin, <Esc> to exit." },
   { d_keyboard_proc,   0,     0,   0,    0,              0,   0,    0,    0, KEY_ENTER,  KEY_SPACE,    interp },
   { d_popup_menu,      0,    20, 800,  580,              0,   0,    0,    0,       0,    0,    menu },
   { NULL,              0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL }
};


#define DIALOG_NAME     7
#define DIALOG_DESC     8

/*************************************************************************
 *
 * int gfx_mode()
 *
 * Set the video mode to SVGA 800x600
 * Autodetect graphics card.
 * Set some palettes.
 *
 *************************************************************************/

int gfx_mode(int x, int y)
{

   if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, x, y, 0, 0) != 0) {
      if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, x, y, 0, 0) != 0) {
         allegro_exit();
         fprintf(stderr,"Error: %dx%d graphics mode not found.\n",x,y);
         exit(1);
      }
   }


   /* set_pallete(desktop_pallete); */

   get_pallete(asm_pallete);

   vsync();
   set_color(ASM_FG_COLOR   , &asm_gui_fg_color);
   set_color(gui_fg_color   , &asm_gui_fg_color);
   set_color(ASM_EMPH_COLOR , &asm_emph_color  );
   set_color(ASM_RED_COLOR  , &asm_red_color   );
   set_color(gui_bg_color   , &asm_gui_bg_color);
   set_color(ASM_BLACK_COLOR, &asm_black_color );
   set_color(ASM_GRAY_COLOR , &asm_gray_color  );
   set_color(ASM_GREEN_COLOR, &asm_green_color );
   set_color(ASM_BLUE_COLOR , &asm_blue_color  );

   sprintf(gfx_specs, "%dx%d (%dx%d), %ldk vram",
     SCREEN_W, SCREEN_H, VIRTUAL_W, VIRTUAL_H, gfx_driver->vid_mem/1024);

   if (!gfx_driver->linear)
      sprintf(gfx_specs+strlen(gfx_specs), ", %ldk banks, %ldk granularity",
         gfx_driver->bank_size/1024, gfx_driver->bank_gran/1024);

   title_screen[DIALOG_NAME].dp = gfx_driver->name;
   title_screen[DIALOG_DESC].dp = gfx_driver->desc;

   return 0;
}

/************************************************************************
 *
 *
 *
 ************************************************************************/


void printhelp()
{
     printf("ASM  - Another Signal Manager (DOS version)\n");
     printf("     - Version %s\n\n",ASM_VERSION);
     printf("Usage:   asm [-h] [-x]\n");
     printf("  -h    = Print this help.\n");
     printf("  -l    = SVGA 800x600 mode\n");
     printf("  -x    = SVGA 1024x768 mode (default)\n\n");
     printf("e-mail:   waterlan@xs4all.nl\n");
}

/************************************************************************
 *
 * Main function
 *
 ************************************************************************/

int main(int argc, char ** argv)
{
   int i, buttons;
   time_t timer;
   char *ctijd;
   DATAFILE *dat;
   int font_nr = a_8x8 ;

   /* ---------------------- parse the commandline ------------*/


   for (i=1; i < argc; i++)
   {
   	if (*argv[i]=='-' ALT_SW) /* is it a switch? */
   		switch (argv[i][1]) {
   		case 'H':
   		case 'h':
   		case '?':
   			printhelp();
    		    return 0;
   			break;
   		case 'X':
   		case 'x':
   			x_res=1024;
   			y_res=768;
   			font_nr = xm9x15;
   			break;
   		case 'L':
   		case 'l':
   			x_res=800;
   			y_res=600;
   			font_nr = a_8x8 ;
   			break;
   		default:               /* any switch except the above */
   			printhelp();
    		    return 0;
   		  	break;
   		}
   	else /* Not a switch.  */
   	{
   	}
   } /* for */


   /*--- end parsing commandline -----------*/


   if  ( (logfile = fopen(ASM_LOG_FILE,"a")) != NULL ) {
      time(&timer);
      ctijd = asctime(localtime(&timer));
      fprintf(logfile,"\n=================================================\n");
      fprintf(logfile,"ASM session:  %s\n",ctijd);
      fprintf(logfile,"=================================================\n");
}

   allegro_init();

   buttons = install_mouse();
   sprintf(mouse_specs, "Mouse has %d buttons", buttons);

   install_keyboard();
   install_timer();

   dat = load_datafile("asm.dat");
   if (dat){
      font = ( FONT*)dat[font_nr].dat; 
   }
   asm_font_width = text_length(font,"A");

   gfx_mode(x_res,y_res);

   solid_mode();
   config();

   do_dialog(title_screen, -1);

   fprintf(logfile,"Normal exit\nbye.\n");

   if(logfile)
   fclose(logfile);

   /* free allocated memory by signals */
   for (i=number_of_signals;i > 0 ; i--)
      remove_venster(vp[i-1]);

   allegro_exit();
   printf("Normal exit\nbye.\n");
   exit(0);
}
END_OF_MAIN()
