/*----------------------------------------------------------------------------*
 | This file is part of DEU (Doom Editing Utilities), created by the DEU team:|
 | Raphael Quinet, Brendon Wyber, Ted Vessenes and others.  See README.1ST or |
 | the "about" dialog box for full credits.                                   |
 |                                                                            |
 | DEU is an open project: if you think that you can contribute, please join  |
 | the DEU team.  You will be credited for any code (or ideas) included in    |
 | the next version of the program.                                           |
 |                                                                            |
 | If you want to make any modifications and re-distribute them on your own,  |
 | you must follow the conditions of the DEU license.  Read the file LICENSE  |
 | in this directory or README.1ST in the top directory.  If do not have a    |
 | copy of these files, you can request them from any member of the DEU team, |
 | or by mail: Raphael Quinet, Rue des Martyrs 9, B-4550 Nandrin (Belgium).   |
 |                                                                            |
 | This program comes with absolutely no warranty.  Use it at your own risks! |
 *----------------------------------------------------------------------------*

 I_MENUS.C - Pop-up and pull-down menus

 Pull-down menus created by Dewi Morgan, other routines by Raphael Quinet
*/

/* the includes */
#include "deu.h"
#include "d_misc.h"
#include "g_gfx.h"
#include "g_mouse.h"
#include "i_dialog.h"
#include "i_menus.h"

/*
   Draws a line of text in a menu.
*/

static void DisplayMenuText(Int16 x0, Int16 y0, Int16 line, char *text, Int16 highlightnum, Bool shownumbers)
{
  char h[2];
  
  if (UseMouse)
    HideMousePointer();
  if (shownumbers)
    {
      DrawScreenText(x0 + 26, y0 + 8 + line * 10, "- %s", text);
      SetColor(WHITE);
      if (line < 9)
        DrawScreenText(x0 + 10, y0 + 8 + line * 10, "%d", line + 1, text);
      else
        DrawScreenText(x0 + 10, y0 + 8 + line * 10, "%c", line + 56, text);
    }
  else
    {
      if (highlightnum > 0)
        {
          DrawScreenText(x0 + 10, y0 + 8 + line * 10, text);
          SetColor(WHITE);
          h[0] = text[highlightnum - 1];
          h[1] = '\0';
          DrawScreenText(x0 + 2 + highlightnum * 8, y0 + 8 + line * 10, h);
        }
      else
        {
          SetColor(DARKGRAY);
          DrawScreenText(x0 + 10, y0 + 8 + line * 10, text);
        }
    }
  if (UseMouse)
    ShowMousePointer();
}


/*
   Display and execute a menu.
*/

static Int16 DisplayMenuArray(Int16 x0, Int16 y0, char *menutitle, Int16 numitems, Int16 *okkeys, char *menustr[30], Int16 highlight[30])
{
  Int16  maxlen, line, oldline;
  Bool   ok;
  Int16  key;
  UInt16 buttons, oldbuttons;

  /* compute maxlen */
  if (menutitle)
    maxlen = strlen(menutitle) - 2;
  else
    maxlen = 1;
  for (line = 0; line < numitems; line++)
    if (strlen(menustr[line]) > maxlen)
      maxlen = strlen(menustr[line]);
#ifndef DEU_DOS
  /* Quick hack: remap the tick mark (different charsets). */
  for (line = 0; line < numitems; line++)
    if (menustr[line][0] == 0xfb)
      menustr[line][0] = 0x03;
#endif

  /* display the menu */
  if (UseMouse)
    HideMousePointer();
  if (x0 < 0)
    x0 = (ScrMaxX - maxlen * 8 - (okkeys ? 19 : 53)) / 2;
  if (y0 < 0)
    y0 = (ScrMaxY - numitems * 10 - (menutitle ? 28 : 12)) / 2;
  if (x0 > ScrMaxX - maxlen * 8 - (okkeys ? 19 : 53))
    x0 = ScrMaxX - maxlen * 8 - (okkeys ? 19 : 53);
  DrawScreenBox3D(x0, y0, x0 + maxlen * 8 + (okkeys ? 19 : 53), y0 + numitems * 10 + (menutitle ? 28 : 12));
  SetColor(YELLOW);
  if (menutitle)
    DrawScreenText(x0 + 10, y0 + 8, menutitle);
  if (UseMouse)
    ShowMousePointer();
  for (line = 0; line < numitems; line++)
    {
      SetColor(BLACK);
      DisplayMenuText(x0, y0 + (menutitle ? 16 : 0), line, menustr[line], highlight[line], !okkeys);
    }
  oldline = -1;
  line = 0;
  oldbuttons = 0x0000;
  ok = FALSE;

  while (! ok)
    {
      if (UseMouse)
        {
          GetMouseCoords(&PointerX, &PointerY, &buttons);
          /* right button = cancel */
          if ((buttons & 0x0002) == 0x0002)
            {
              line = -1;
              ok = TRUE;
            }
          /* left button = select */
          else if (buttons == 0x0001 && (Int16) PointerX >= x0 && (Int16) PointerX <= x0 + maxlen * 8 + 53)
            line = (PointerY - y0 - (menutitle ? 24 : 8)) / 10;
          /* release left button = accept selection */
         else if (buttons == 0x0000 && oldbuttons == 0x0001)
           ok = TRUE;
          oldbuttons = buttons;
        }
      if (IsKeyPressed())
        {
          key = WaitForKey();

          /* enter key = accept selection */
         if ((key & 0x00FF) == 0x000D)
           ok = TRUE;
         /* escape key = cancel */
         else if ((key & 0x00FF) == 0x001B)
           {
             line = -1;
             ok = TRUE;
           }
          /* up arrow = select previous line */
         else if ((key & 0xFF00) == 0x4800)
           {
             if (line > 0)
               line--;
             else
               line = numitems - 1;
           }
          /* down arrow = select next line */
         else if ((key & 0xFF00) == 0x5000)
           {
             if (line < numitems - 1)
               line++;
             else
               line = 0;
           }
          /* home = select first line */
         else if ((key & 0xFF00) == 0x4700)
           line = 0;
          /* end = select last line */
         else if ((key & 0xFF00) == 0x4F00)
           line = numitems - 1;
          /* pgup = select line - 5 */
         else if ((key & 0xFF00) == 0x4900)
           {
             if (line >= 5)
               line -= 5;
             else
               line = 0;
           }
          /* pgdn = select line + 5 */
         else if ((key & 0xFF00) == 0x5100)
           {
            if (line < numitems - 5)
              line += 5;
            else
              line = numitems - 1;
          }
          /* number or alphabetic key = enter selection */
         else if ((key & 0x00FF) >= '1' && (key & 0x00FF) <= '9' && ((key & 0x00FF) - '1') < numitems)
           {
             line = (key & 0x00FF) - '1';
             ok = TRUE;
           }
         else if ((key & 0x00FF) >= 'A' && (key & 0x00FF) <= 'Z' && ((key & 0x00FF) - 'A' + 9) < numitems)
           {
             line = (key & 0x00FF) - 'A' + 9;
             ok = TRUE;
           }
         else if ((key & 0x00FF) >= 'a' && (key & 0x00FF) <= 'z' && ((key & 0x00FF) - 'a' + 9) < numitems)
           {
             line = (key & 0x00FF) - 'a' + 9;
             ok = TRUE;
           }
          /* check the list of "hot keys" */
         else if (okkeys)
           {
             for (line = 0; line < numitems; line++)
               if (toupper(key & 0x00FF ) == okkeys[line])
                 break;
             if (line < numitems)
               ok = TRUE;
             else
               {
                 line = oldline;
                 Beep();
               }
           }
          /* other key */
         else
           Beep();
        }
      if (line != oldline)
        {
          if (oldline >= 0 && oldline < numitems)
            {
              SetColor(BLACK);
              DisplayMenuText(x0, y0 + (menutitle ? 16 : 0), oldline, menustr[oldline], highlight[oldline], !okkeys);
            }
          if (line >= 0 && line < numitems)
            {
              SetColor(WHITE);
              DisplayMenuText(x0, y0 + (menutitle ? 16 : 0), line, menustr[line], highlight[line], !okkeys);
            }
          oldline = line;
        }
    }
  if (line >= 0 && line < numitems)
    return (line + 1);
  else
    return 0;
}


/*
   Display and execute a menu defined with variable arguments.
*/

Int16 DisplayMenu(Int16 x0, Int16 y0, char *menutitle, ...)
{
  va_list args;
  Int16   num;
  char   *menustr[30];
  Int16   dummy[30];

  /* put the va_args in the menustr table */
  num = 0;
  va_start(args, menutitle);
  while ((num < 30) && ((menustr[num] = va_arg(args, char *)) != NULL))
    num++;
  va_end(args);
  
  /* display the menu */
  return DisplayMenuArray(x0, y0, menutitle, num, NULL, menustr, dummy);
}


/*
   Display and execute a dropdown menu (returns a key code).
*/

Int16 PullDownMenu(Int16 x0, Int16 y0, ...)
{
  va_list args;
  Int16   num;
  char   *menustr[30];
  Int16   retnkeys[30];
  Int16   permkeys[30];
  Int16   highlight[30];

  /* put the va_args in the menustr table and the two strings */
  num = 0;
  va_start(args, y0);
  while ((num < 30) && ((menustr[num] = va_arg(args, char *)) != NULL))
    {
      if (!(retnkeys[num] = (Int16) va_arg(args, int)))
        ProgError("BUG: PullDownMenu() called with invalid arguments");
      if (!(permkeys[num] = (Int16) va_arg(args, int)))
        ProgError("BUG: PullDownMenu() called with invalid arguments");
      if (!(highlight[num] = (Int16) va_arg(args, int)))
        ProgError("BUG: PullDownMenu() called with invalid arguments");
      num++;
    }
  va_end(args);

  /* display the menu */
  num = DisplayMenuArray(x0, y0, NULL, num, permkeys, menustr, highlight);
  if (num >= 1)
    return retnkeys[num - 1]; /* return a valid key */
  else
    return 0; /* return an invalid key */
}


/*
   Display the integer input box.
*/


/*! NOT USED? */


Int16 InputInteger(Int16 x0, Int16 y0, Int16 *valp, Int16 minv, Int16 maxv)
{
  Int16 key, val;
  Bool  neg, ok, firstkey;

  DrawScreenBoxHollow(x0, y0, x0 + 61, y0 + 13);
  neg = (*valp < 0);
  val = neg ? -(*valp) : *valp;
  firstkey = TRUE;
  for (;;)
    {
      ok = (neg ? -val : val) >= minv && (neg ? -val : val) <= maxv;
      SetColor(BLACK);
      DrawScreenBox(x0 + 1, y0 + 1, x0 + 60, y0 + 12);
      if (ok)
        SetColor(WHITE);
      else
        SetColor(LIGHTGRAY);
      if (neg)
        DrawScreenText(x0 + 3, y0 + 3, "-%d", val);
      else
        DrawScreenText(x0 + 3, y0 + 3, "%d", val);
      key = WaitForKey();
      if (firstkey && (key & 0x00FF) > ' ')
        {
          val = 0;
          neg = FALSE;
        }
      firstkey = FALSE;
      if (val < 3275 && (key & 0x00FF) >= '0' && (key & 0x00FF) <= '9')
        val = val * 10 + (key & 0x00FF) - '0';
      else if (val > 0 && (key & 0x00FF) == 0x0008)
        val = val / 10;
      else if (neg && (key & 0x00FF) == 0x0008)
        neg = FALSE;
      else if ((key & 0x00FF) == '-')
        neg = !neg;
      else if (ok && (key & 0x00FF) == 0x000D)
        break; /* return "val" */
      else if ((key & 0xFF00) == 0x4800 || (key & 0xFF00) == 0x5000 ||
               (key & 0xFF00) == 0x4B00 || (key & 0xFF00) == 0x4D00 ||
               (key & 0x00FF) == 0x0009 || (key & 0xFF00) == 0x0F00)
        break; /* return "val", even if not valid */
      else if ((key & 0x00FF) == 0x001B)
        {
          neg = FALSE;
          val = -32767; /* return a value out of range */
          break;
        }
      else
        Beep();
    }
  if (neg)
    *valp = -val;
  else
    *valp = val;
  return key;
}


/*
   Ask for an integer value and check for minimum and maximum.
   If prompt is NULL, a default message is printed instead.
*/

Int16 InputIntegerValue(Int16 x0, Int16 y0, char *prompt, Int16 minv, Int16 maxv, Int16 defv)
{
  Int16 val;
  char  tmp_prompt[80];

  if (prompt == NULL)
    {
      prompt = tmp_prompt;
      sprintf(prompt, "Enter a decimal number between %d and %d:", minv, maxv);
    }
  val = defv;
  if (DrawDialogBox(x0, y0, 25 + TEXT_W * strlen(prompt), 68, NULL, 5,
                    DBSC_TEXT,     -0x0102,  8, '\0', prompt, 0, WHITE,
                    DBSC_TEXT,          12, 25,  'I', "Input:", 0, YELLOW,
                    DBSC_INPUTBOX,      68, 23,  'I', &val, minv, maxv,
                    DBSC_OK,       -0x0104, 43,  'O',
                    DBSC_CANCEL,   -0x0304, 43,  'C') == TRUE)
    return val;
  else
    return -32767;
}


/*
   Ask for a name in a given list and call a function (for displaying objects, etc.)

   Arguments:
      x0, y0  : where to draw the box.
      prompt  : text to be displayed.
      listsize: number of elements in the list.
      list    : list of names (picture names, level names, etc.).
      listdisp: number of lines that should be displayed.
      name    : what we are editing...
      width   : \ width and height of an optional window where a picture
      height  : / can be displayed (used to display textures, sprites, etc.).
      hookfunc: function that should be called to display a picture.
                (x1, y1, x2, y2 = coordinates of the window in which the
                picture must be drawn, name = name of the picture).
*/

void InputNameFromListWithFunc(Int16 x0, Int16 y0, char *prompt, Int16 listsize, char **list, Int16 listdisp, char *name, Int16 width, Int16 height, void (*hookfunc)(Int16 px1, Int16 py1, Int16 px2, Int16 py2, char *name))
{
  Int16 key, n, l;
  Int16 x1, y1, x2, y2;
  Int16 maxlen;
  Bool  ok, firstkey, redraw;
  Int16 bwidth, bheight;

  /* compute maxlen */
  maxlen = 1;
  for (n = 0; n < listsize; n++)
    if (strlen(list[n]) > maxlen)
      maxlen = strlen(list[n]);
  for (n = strlen(name) + 1; n <= maxlen; n++)
    name[n] = '\0';
  /* compute the width of the dialog box */
  bwidth = maxlen;
  if (strlen(prompt) > bwidth + 12)
    bwidth = strlen(prompt) - 12;
  bwidth = bwidth * 8 + 110;
  x1 = bwidth + 3;
  y1 = 10 + 1;
  if (width > 0)
    bwidth += 10 + width;
  /* compute the height of the dialog box */
  if (height > 65)
    bheight = height + 20;
  else
    bheight = 85;
  /* position of the dialog box and the optional picture */
  if (x0 < 0)
    x0 = (ScrMaxX - bwidth) / 2;
  if (y0 < 0)
    y0 = (ScrMaxY - bheight) / 2;
  x1 += x0;
  y1 += y0;
  if (x1 + width - 1 < ScrMaxX)
    x2 = x1 + width - 1;
  else
    x2 = ScrMaxX;
  if (y1 + height - 1 < ScrMaxY)
    y2 = y1 + height - 1;
  else
      y2 = ScrMaxY;
  firstkey = TRUE;
  redraw = TRUE;
  for (;;)
    {
      if (redraw == TRUE)
        {
          /* (re)draw the dialog box */
          DrawScreenBox3D(x0, y0, x0 + bwidth, y0 + bheight);
          DrawScreenBoxHollow(x0 + 10, y0 + 28, x0 + 101, y0 + 41);
          DrawScreenText(x0 + 10, y0 + 8, prompt);
          if (width > 0)
            {
              DrawScreenBox(x1, y1, x2 + 1, y2 + 1);
              SetColor(DARKGRAY);
              DrawScreenBox(x1 - 1, y1 - 1, x2, y2);
            }
          redraw = FALSE;
        }
      /* test if "name" is in the list */
      for (n = 0; n < listsize; n++)
        if (strcmp(name, list[n]) <= 0)
          break;
      ok = n < listsize ? !strcmp(name, list[n]) : FALSE;
      if (n > listsize - 1)
        n = listsize - 1;
      /* display the "listdisp" next items in the list */
      SetColor(LIGHTGRAY);
      DrawScreenBox(x0 + 110, y0 + 30, x0 + 110 + 8 * maxlen, y0 + 30 + 10 * listdisp);
      SetColor(BLACK);
      for (l = 0; l < listdisp && n + l < listsize; l++)
        DrawScreenText(x0 + 110, y0 + 30 + l * 10, list[n + l]);
      l = strlen(name);
      DrawScreenBox(x0 + 11, y0 + 29, x0 + 100, y0 + 40);
      if (ok)
        SetColor(WHITE);
      else
        SetColor(LIGHTGRAY);
      DrawScreenText(x0 + 13, y0 + 31, name);
      /* call the function to display the picture, if any */
      if (hookfunc)
        {
          /* clear the window */
          SetColor(BLACK);
          DrawScreenBox(x1, y1, x2, y2);
          /* display the picture "name" */
          hookfunc(x1, y1, x2, y2, name);
        }
      /* process user input */
      key = WaitForKey();
#if defined(DEU_GFX_X11) || defined(DEU_GFX_SGI)
      /* hack for X Window which may require a redraw at any time */
      if (key == MAGIC_REDRAW_KEY)
        {
          redraw = TRUE;
          continue;
        }
#endif
      if (firstkey && (key & 0x00FF) > ' ')
        {
          for (l = 0; l <= maxlen; l++)
            name[l] = '\0';
          l = 0;
        }
      firstkey = FALSE;
      if (l < maxlen && (key & 0x00FF) >= 'a' && (key & 0x00FF) <= 'z')
        {
          name[l] = (key & 0x00FF) + 'A' - 'a';
          name[l + 1] = '\0';
        }
      else if (l < maxlen && (key & 0x00FF) > ' ')
        {
          name[l] = key & 0x00FF;
          name[l + 1] = '\0';
        }
      else if (l > 0 && (key & 0x00FF) == 0x0008)
        name[l - 1] = '\0';
      else if (n < listsize - 1 && (key & 0xFF00) == 0x5000)
        strcpy(name, list[n + 1]);
      else if (n > 0 && (key & 0xFF00) == 0x4800)
        strcpy(name, list[n - 1]);
      else if (n < listsize - listdisp && (key & 0xFF00) == 0x5100)
        strcpy(name, list[n + listdisp]);
      else if (n > 0 && (key & 0xFF00) == 0x4900)
        {
          if (n > listdisp)
            strcpy(name, list[n - listdisp]);
          else
            strcpy(name, list[0]);
        }
      else if ((key & 0xFF00) == 0x4F00)
        strcpy(name, list[listsize - 1]);
      else if ((key & 0xFF00) == 0x4700)
        strcpy(name, list[0]);
      else if ((key & 0x00FF) == 0x0009)
        strcpy(name, list[n]);
      else if (ok && (key & 0x00FF) == 0x000D)
        break; /* return "name" */
      else if ((key & 0x00FF) == 0x001B)
        {
          name[0] = '\0'; /* return an empty string */
          break;
        }
      else
        Beep();
    }
}


/*
   Ask for a name in a given list.
*/

void InputNameFromList(Int16 x0, Int16 y0, char *prompt, Int16 listsize, char **list, char *name)
{
  if (UseMouse)
    HideMousePointer();
  InputNameFromListWithFunc(x0, y0, prompt, listsize, list, 5, name, 0, 0, NULL);
  if (UseMouse)
    ShowMousePointer();
}


/*
   Ask for a filename.
*/

void InputFileName(Int16 x0, Int16 y0, char *prompt, Int16 maxlen, char *filename)
{
  Int16  key, l, boxlen;
  Bool   ok, firstkey;
  char  *p;

  if (UseMouse)
    HideMousePointer();
  for (l = strlen(filename) + 1; l <= maxlen; l++)
    filename[l] = '\0';
  /* compute the width of the input box */
  if (maxlen > 20)
    boxlen = 20;
  else
    boxlen = maxlen;
  /* compute the width of the dialog box */
  if (strlen(prompt) > boxlen)
    l = strlen(prompt);
  else
    l = boxlen;
  if (x0 < 0)
    x0 = (ScrMaxX - 26 - 8 * l) / 2;
  if (y0 < 0)
    y0 = (ScrMaxY - 50) / 2;
  /* draw the dialog box */
  DrawScreenBox3D(x0, y0, x0 + 26 + 8 * l, y0 + 50);
  DrawScreenBoxHollow(x0 + 10, y0 + 28, x0 + 15 + 8 * boxlen, y0 + 41);
  DrawScreenText(x0 + 10, y0 + 8, prompt);
  firstkey = TRUE;
  for (;;)
    {
      /* check that "filename" looks like a valid file name */
      ok = TRUE;
      if (filename[1] == ':')
        p = filename + 2;
      else
        p = filename;
      for (l = 8; *p; p++)
        {
          if (*p == '.')
            l = 3;
          else if (*p == '\\')
            l = 8;
          else
            l--;
          if (l < 0)
            {
              ok = FALSE;
              break;
            }
        }
      
      l = strlen(filename);
      SetColor(BLACK);
      DrawScreenBox(x0 + 11, y0 + 29, x0 + 14 + 8 * boxlen, y0 + 40);
      if (ok)
        SetColor(WHITE);
      else
        SetColor(LIGHTGRAY);
      if (l > boxlen)
        {
          DrawScreenText(x0 + 11, y0 + 31, "<");
          DrawScreenText(x0 + 13, y0 + 31, "<%s", filename + (l - boxlen + 1));
        }
      else
        DrawScreenText(x0 + 13, y0 + 31, filename);
      key = WaitForKey();
      if (firstkey && (key & 0x00FF) > ' ')
        {
          for (l = 0; l <= maxlen; l++)
            filename[l] = '\0';
          l = 0;
        }
      firstkey = FALSE;
      if (l < maxlen && (key & 0x00FF) >= 'a' && (key & 0x00FF) <= 'z')
        {
          filename[l] = (key & 0x00FF) + 'A' - 'a';
          filename[l + 1] = '\0';
        }
      else if (l < maxlen && (key & 0x00FF) > ' ')
        {
          filename[l] = key & 0x00FF;
          filename[l + 1] = '\0';
        }
      else if (l > 0 && (key & 0x00FF) == 0x0008)
        filename[l - 1] = '\0';
      else if (ok && (key & 0x00FF) == 0x000D)
        break; /* return "filename" */
      else if ((key & 0x00FF) == 0x001B)
        {
          filename[0] = '\0'; /* return an empty string */
          break;
        }
      else
        Beep();
    }
  if (UseMouse)
    ShowMousePointer();
}


/*
   Ask for confirmation (prompt2 may be NULL).
*/

Bool Confirm(Int16 x0, Int16 y0, char *prompt1, char *prompt2)
{
  Int16 maxlen;
  Int16 width;
  Bool  input;
  
  maxlen = 2 * BUTTON_W / TEXT_W;
  if (prompt2 == NULL)
    {
      maxlen = MAX(maxlen, strlen(prompt1));
      width = 22 + TEXT_W * maxlen;
      input = DrawDialogBox(x0, y0, width, 54, NULL, 3,
                            DBSC_TEXT,   -0x0102, 8, '\0', prompt1, 0, WHITE,
                            DBSC_OK,     -0x0103, 28, 'O',
                            DBSC_CANCEL, -0x0203, 28, 'C');
    }
  else
    {
      maxlen = MAX(maxlen, MAX(strlen(prompt1), strlen(prompt2)));
      width = 22 + TEXT_W * maxlen;
      input = DrawDialogBox(x0, y0, width, 64, NULL, 4,
                            DBSC_TEXT, -0x0102,  8, '\0', prompt1, 0, WHITE,
                            DBSC_TEXT, -0x0102, 18, '\0', prompt2, 0, WHITE,
                            DBSC_OK,     -0x0103, 38, 'O',
                            DBSC_CANCEL, -0x0203, 38, 'C');
    } 
  return input;
}



/*
   Display a notification and wait for a key (prompt2 may be NULL).
*/

void Notify(Int16 x0, Int16 y0, char *prompt1, char *prompt2)
{
  Int16 maxlen;

  maxlen = BUTTON_W / TEXT_W;
  if (prompt2 == NULL)
    {
      maxlen = MAX(maxlen, strlen(prompt1));
      DrawDialogBox(x0, y0, 22 + TEXT_W * maxlen, 54, NULL, 2,
                    DBSC_TEXT,   -0x0102, 8, '\0', prompt1, 0, WHITE,
                    DBSC_OK,     -0x0102, 28, 'O');
    }
  else
    {
      maxlen = MAX(maxlen, MAX(strlen(prompt1), strlen(prompt2)));
      DrawDialogBox(x0, y0, 22 + TEXT_W * maxlen, 64, NULL, 3,
                    DBSC_TEXT,   -0x0102,  8, '\0', prompt1, 0, WHITE,
                    DBSC_TEXT,   -0x0102, 18, '\0', prompt2, 0, WHITE,
                    DBSC_OK,     -0x0102, 38,  'O');
    }
}


/*
   Clear the screen and display a message.
*/

void DisplayMessage(Int16 x0, Int16 y0, char *msg, ...)
{
   char    prompt[120];
   va_list args;

   va_start(args, msg);
   vsprintf(prompt, msg, args);
   va_end(args);

   if (UseMouse)
     HideMousePointer();
   ClearScreen();
   if (x0 < 0)
     x0 = (ScrMaxX - 40 - 8 * strlen(prompt)) / 2;
   if (y0 < 0)
     y0 = (ScrMaxY - 40) / 2;
   DrawScreenBox3D(x0, y0, x0 + 40 + 8 * strlen(prompt), y0 + 40);
   DrawScreenText(x0 + 20, y0 + 17, prompt);
   if (UseMouse)
     ShowMousePointer();
}


/* coordinates of the meter bar */
static int mx0, my0, mx1, my1;


/*
   Display a message and a meter bar (prompt may be NULL).
*/

void DisplayProgressMeter(Int16 x0, Int16 y0, Int16 minwidth, char *prompt)
{
  if (UseMouse)
    HideMousePointer();
  if (prompt == NULL)
    prompt = "Please wait...";
  minwidth = 20 + MAX(minwidth, 8 * strlen(prompt));
  if (x0 < 0)
    x0 = (ScrMaxX - minwidth) / 2;
  if (y0 < 0)
    y0 = (ScrMaxY - 46) / 2;
  DrawScreenBox3D(x0, y0, x0 + minwidth, y0 + 46);
  SetColor(WHITE);
  DrawScreenText(x0 + 10, y0 + 8, prompt);
  /* Keep these values for the next call */
  mx0 = x0 + 10;
  my0 = y0 + 18;
  mx1 = x0 + minwidth - 10;
  my1 = y0 + 38;
  DrawScreenBoxHollow(mx0, my0, mx1, my1);
  DrawScreenMeter(mx0, my0, mx1, my1, 0.0);
  if (UseMouse)
    ShowMousePointer();
}



/*
   Update the progress meter that has been drawn by the previous function.
*/

void UpdateProgressMeter(float value)
{
  if (UseMouse)
    HideMousePointer();
  DrawScreenMeter(mx0, my0, mx1, my1, value);
  if (UseMouse)
    ShowMousePointer();
}



/*
   Let's make the user angry...
*/

void NotImplemented(void)
{
  DrawDialogBox(-1, -1, 340, 50, NULL, 2,
                DBSC_TEXT, -0x0102, 10, '\0',
                "This function is not implemented... Yet!", 0, RED,
                DBSC_OK,   -0x0102, 25,  'O');
}

/* end of file */
