/*
 * (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
 *
 * for details see file COPYING in the DOSEMU distribution
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "emu.h"
#include "memory.h"
#include "video.h"
#include "builtins.h"
#include "doshelpers.h"
#include "xmode.h"

static int X_change_config(unsigned, void *, int);

int xmode_main(int argc, char **argv)
{
  char *p;
  long l, ll[2];


  argv++;
  if(!--argc) {
    com_fprintf(com_stderr,
      "usage: xmode <some arguments>\n"
      "  -mode <mode>     activate graphics/text mode\n"
      "  -vmem_a0 on|off  use vmem at 0xa0000 (off means 64K of RAM)\n"
      "  -vmem_b0 on|off  use vmem at 0xb0000 (off means 32K of RAM)\n"
      "  -title <name>    set name of emulator (in window title)\n"
      "  -showapp on|off  show name of running application (in window title)\n"
      "  -font <font>     use <font> as text font\n"
      "  -custom-font on|off  use custom or VGA font for text modes\n"
      "  -map <mode>      map window after graphics <mode> has been entered\n"
      "  -unmap <mode>    unmap window before graphics <mode> is left\n"
      "  -winsize <width> <height>    set initial graphics window size\n"
      "  -bpause on|off   pause DOSEMU if the window loses focus\n"
      "  -fullscreen on|off           fullscreen mode\n"
      "  -mouse-ungrab-tweak on|off   fix coords problems in ungrabbed mode\n"
    );
    return 0;
  }

  while(argc) {
    if(!strcmp(*argv, "-title") && argc >= 2) {
      X_change_config(CHG_TITLE_EMUNAME, argv[1], strlen(argv[1]) + 1);
      argc -= 2; argv += 2;
    }
    else if (!strcmp(*argv, "-showapp") && argc >= 2) {
      if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0"))
	l = 0;
      else
	l = 1;

      X_change_config(CHG_TITLE_SHOW_APPNAME, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if(!strcmp(*argv, "-font") && argc >= 2) {
      X_change_config(CHG_FONT, argv[1], strlen(argv[1]) + 1);
      argc -= 2; argv += 2;
    }
    else if (!strcmp(*argv, "-custom-font") && argc >= 2) {
      if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0"))
	l = 0;
      else
	l = 1;

      X_change_config(CHG_USE_CUSTOM_FONT, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if(!strcmp(*argv, "-map") && argc >= 2) {
      l = strtol(argv[1], &p, 0);
      if(argv[1] == p) {
        com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]);
        return 2;
      }
      X_change_config(CHG_MAP, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if(!strcmp(*argv, "-unmap") && argc >= 2) {
      l = strtol(argv[1], &p, 0);
      if(argv[1] == p) {
        com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]);
        return 2;
      }
      X_change_config(CHG_UNMAP, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if(!strcmp(*argv, "-winsize") && argc >= 3) {
      ll[0] = strtol(argv[1], &p, 0);
      if(argv[1] == p) {
        com_fprintf(com_stderr, "invalid width \"%s\"\n", argv[1]);
        return 2;
      }
      ll[1] = strtol(argv[2], &p, 0);
      if(argv[2] == p) {
        com_fprintf(com_stderr, "invalid height \"%s\"\n", argv[2]);
        return 2;
      }
      X_change_config(CHG_WINSIZE, ll, sizeof(ll));
      argc -= 3; argv += 3;
    }
    else if(!strcmp(*argv, "-mode") && argc >= 2) {
      l = strtol(argv[1], &p, 0);
      if(argv[1] == p) {
        com_fprintf(com_stderr, "invalid mode number \"%s\"\n", argv[1]);
        return 2;
      }
      if(l & ~0xff) {
        struct REGPACK r = REGPACK_INIT;

        r.r_bx = l & 0xffff;
        r.r_ax = 0x4f02;
        com_intr(0x10, &r);
      }
      else {
        struct REGPACK r = REGPACK_INIT;

        r.r_ax = l & 0xff;
        com_intr(0x10, &r);
      }
      argc -= 2; argv += 2;
    }
    else if (!strncmp(*argv, "-vmem_", 6) && argc >= 2) {
      struct REGPACK r = REGPACK_INIT;
      if (strequalDOS (argv[1], "OFF") || strequalDOS (argv[1], "0"))
	l = 0;
      else
	l = 1;

      r.r_ax = DOS_HELPER_CONTROL_VIDEO;
      r.r_bx = (DOS_SUBHELPER_VIDEO_MAP_a + argv[0][6] - 'a') | (l << 8);
      com_intr(DOS_HELPER_INT, &r);
      argc -= 2; argv += 2;
    }
    else if (!strcmp(*argv, "-bpause") && argc >= 2) {
      if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0"))
	l = 0;
      else
	l = 1;

      X_change_config(CHG_BACKGROUND_PAUSE, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if (!strcmp(*argv, "-fullscreen") && argc >= 2) {
      if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0"))
	l = 0;
      else
	l = 1;

      X_change_config(CHG_FULLSCREEN, &l, sizeof(l));
      argc -= 2; argv += 2;
    }
    else if (!strcmp(*argv, "-mouse-ungrab-tweak") && argc >= 2) {
      if (strequalDOS (argv [1], "OFF") || strequalDOS (argv [1], "0"))
	l = 0;
      else
	l = 1;

      config.mouse.ignore_speed = l;
      argc -= 2; argv += 2;
    }
    else {
      com_fprintf(com_stderr, "Don't know what to do with argument \"%s\"; aborting here.\n", *argv);
      return 2;
    }
  }

  return 0;
}

static int X_change_config(unsigned item, void *buf, int len)
{
  struct REGPACK r = REGPACK_INIT;
  void *lbuf;

  r.r_ax = DOS_HELPER_XCONFIG;
  r.r_cx = len;
  lbuf = lowmem_alloc(len);
  memcpy(lbuf, buf, len);
  r.r_dx = item;
  r.r_es = DOSEMU_LMHEAP_SEG;
  r.r_bx = DOSEMU_LMHEAP_OFFS_OF(lbuf);
  com_intr(DOS_HELPER_INT, &r);
  lowmem_free(lbuf);
  if (r.r_flags & 1) {
    com_printf("xmode helper failed\n");
    return -1;
  }
  return r.r_ax;
}
