#ifndef __EDWIN_CONFIG_H__
#define __EDWIN_CONFIG_H__ 1

#include <perms.h>

int Clipping = 0;
int Device = -1;

static const int Numdev = 13;
static const int Dvx[14 /*0:13*/] = {1023,   1023, 511,   11200, 4000,
                                     0x7FFF, 773,  71,    119,   131,
                                     79,     719,  16000, 16000};
static const int Dvy[14 /*0:13*/] = {767, 767, 511, 8000, 2800, 0x7FFF, 779,
                                     63,  63,  63,  23,   359,  11200,  10800};
static const int Xlim[14 /*0:13*/] = {1023,   4095, 511,   16000, 32000,
                                      0x7FFF, 773,  71,    119,   131,
                                      79,     719,  16000, 16000};
static const int Ylim[14 /*0:13*/] = {767,    4095, 511,   11400, 32000,
                                      0x7FFF, 779,  63,    63,    63,
                                      23,     359,  11200, 10800};
static const float Aspectfactor[14 /*0:13*/] = {1,   1,   1.25, 1,    1, 1, 1.1,
                                                0.5, 0.5, 0.5,  0.45, 1, 1, 1};

static int Viewportgradient(int Y, int X) {
  float Asr;
  if (0 <= Device && Device <= Numdev)
    Asr = (float)Aspectfactor[Device];
  else
    Asr = 1.0;
  // %result = INT (5000*Y/(ASR*X))
  return (INT(5000.0*Y/(Asr*X)));
}

static void Maptovirtualcoords(int *X, int *Y);

#ifdef NEVER // Missing device drivers
extern void T4000(int Com, int X, int Y);
extern void C963(int Com, int X, int Y);
extern void Cats(int Com, int X, int Y);
extern void Chas(int Com, int X, int Y);
extern void Hpplot(int Com, int X, int Y);
extern void P300(int Com, int X, int Y);
extern void Hp2648a(int Com, int X, int Y);
extern void Tcursor(int *Status, int *X, int *Y);
extern void Vcursor(int *Status, int *X, int *Y);
extern void Ccursor(int *Status, int *X, int *Y);
extern void Pcursor(int *Status, int *X, int *Y);
extern void Hcursor(int *Status, int *X, int *Y);
#endif

void Drivedev_inner(int Com, int X, int Y, int line) {
#define Drivedev(Com, X, Y) Drivedev_inner(Com, X, Y, __LINE__)
  static int Sw_sw;
  static void *Sw[14 /*0:13*/] = {
      &&Sw_0, &&Sw_1, &&Sw_2, &&Sw_3,  &&Sw_4,  &&Sw_default, &&Sw_6,
      &&Sw_7, &&Sw_8, &&Sw_9, &&Sw_10, &&Sw_11, &&Sw_12,      &&Sw_13,
  };
  fprintf(stderr, "Line %d: Drivedev(Dev %d: %d,%d,%d)\n", line, Device, Com, X, Y);
  if (!Com) {
    Device = 99;
    if ('a' <= X && X <= 'z') X = X - 'a' + 'A';
    if (!X) Device = -1;
    if (4002 <= X && X <= 4099) Device = 0;
    if (X == 4014) Device = 1;
    if (X == 'C') Device = 2;
    if (X == 7221) Device = 3;
    if (563 <= X && X <= 1051) Device = 4;
    if (X == 300) Device = 6;
    if (X == 'H') Device = 7;
    if (X == 'L') Device = 9;
    if (X == 200 || X == 550) Device = 10;
    if (X == 'E' || X == 'V' || X == 'X') Device = 10;
    if (X == 2648) Device = 11;
    if (X == 7580) Device = 12;
    if (X == 7220) Device = 13;
  }
  if (Device < 0) return;
  if (Device > Numdev) {
    Device = -1;
    _imp_signal(14, 0, 0, _imp_str_literal(""));
  }
  fprintf(stderr, "B: Drivedev(Dev %d: %d,%d,%d)\n", Device, Com, X, Y);
  goto *Sw[Sw_sw = Device];
Sw_0:;
Sw_1:
#ifdef NEVER
  T4000(Com, X, Y);
#endif
  return;
Sw_2:
#ifdef NEVER
  Chas(Com, X, Y);
#endif
  return;
Sw_12:;
Sw_3:
#ifdef NEVER
  Hpplot(Com, X, Y);
#endif
  return;
Sw_13:;
Sw_4:
#ifdef NEVER
  C963(Com, X, Y);
#endif
  return;
Sw_6:
#ifdef NEVER
  P300(Com, X, Y);
#endif
  return;
Sw_7:;
Sw_8:;
Sw_9:;
Sw_10:
#ifdef NEVER
  Cats(Com, X, Y);
#endif
  return;
Sw_11:
#ifdef NEVER
  Hp2648a(Com, X, Y);
#endif
  return;
  goto Sw_skip;
Sw_default:
  fprintf(stderr, "\nSwitch label 'Sw(%d):' not set in %s\n", Sw_sw,
          __PRETTY_FUNCTION__);
  fflush(stderr);
  abort();
Sw_skip:;
}
extern void Dcursor(int *State, int *X, int *Y) {
  static int Dc_sw;
  static void *Dc[14 /*0:13*/] = {
      &&Dc_0,       &&Dc_1,       &&Dc_2,       &&Dc_3,       &&Dc_default,
      &&Dc_default, &&Dc_default, &&Dc_default, &&Dc_default, &&Dc_default,
      &&Dc_10,      &&Dc_11,      &&Dc_default, &&Dc_default,
  };
  if (Device < 0 || Device > Numdev)
    _imp_signal(14, 8, 0, _imp_str_literal(""));
  goto *Dc[Dc_sw = Device];
Dc_0:;
Dc_1:
#ifdef NEVER
  Tcursor(State, X, Y);
#endif
  return;
Dc_2:
#ifdef NEVER
  Ccursor(State, X, Y);
#endif
  return;
Dc_3:
#ifdef NEVER
  Pcursor(State, X, Y);
#endif
  return;
Dc_10:
#ifdef NEVER
  Vcursor(State, X, Y);
#endif
  return;
Dc_11:
#ifdef NEVER
  Hcursor(State, X, Y);
#endif
  return;
Dc_default:;
}
extern void Cursor(int *State, int *X, int *Y) {
  Dcursor(State, X, Y);
  Maptovirtualcoords(X, Y);
}
_imp_string Devicename(void) {
  static const _imp_string Names[14 /*0:13*/] = {
      _imp_str_literal("Tektronix"),
      _imp_str_literal("Tektronix 4014"),
      _imp_str_literal("Charles"),
      _imp_str_literal("HP 7221 plotter"),
      _imp_str_literal("Calcomp plotter"),
      _imp_str_literal("Applicon plotter"),
      _imp_str_literal("Printronix printer"),
      _imp_str_literal("Terminal of width 72"),
      _imp_str_literal("Line printer of width 120"),
      _imp_str_literal("Line printer of width 132"),
      _imp_str_literal("Cursor Addressable Terminal"),
      _imp_str_literal("HP 2648 raster-scan terminal"),
      _imp_str_literal("HP 7580 plotter"),
      _imp_str_literal("HP 7220 plotter")};
  if (0 > Device || Device > Numdev) return (_imp_str_literal("null"));
  return (Names[Device]);
}
_imp_string Edwinerror(int I) {
  static const int Maxerror = 11;
  static const _imp_string Errors[12 /*0:11*/] = {
      _imp_str_literal("Initialisation failed - unknown device"),
      _imp_str_literal("Initialisation failed in device driver"),
      _imp_str_literal("Internal error"),
      [3 ... 4] = _imp_str_literal("Undefined"),
      _imp_str_literal("Corrupt PDF"),
      _imp_str_literal("Unknown attribute change"),
      _imp_str_literal("Internal error in SHAPES"),
      _imp_str_literal("Invalid routine call"),
      _imp_str_literal("Transformation stack not initialised?"),
      _imp_str_literal("Transformation stack overflow"),
      _imp_str_literal("Transformation stack underflow")};
  if (0 > I || I > Maxerror)
    return (_imp_str_literal("EDWIN error out of range"));
  return (Errors[I]);
}
int Defaultdevice(void) {
  int Uinfi(int W);
  static const int Maxdev = 20;
  static const int Defs[21 /*0:20*/] = {0,   0, 0,   0, 0, 0, 550,  0, 0, 0, 0,
                                        200, 0, 'E', 0, 0, 0, 4010, 0, 0, 0};
  int D;
  D = Uinfi(23);
  if (0 > D || D > Maxdev) return (0);
  return (Defs[D]);
}
#endif
