예제 #1
0
파일: plugin.c 프로젝트: albertocabello/gr
static
void *load_library(const char *name)
{
  char pathname[MAXPATHLEN], symbol[255];
#ifdef _WIN32
  HINSTANCE handle;
#else
  void *handle;
  const char *error;
#endif
  void *entry = NULL;

  sprintf(pathname, "%s.%s", name, EXTENSION);
#ifdef _WIN32
  handle = LoadLibrary(pathname);
#else
  handle = dlopen(pathname, RTLD_LAZY);
  if (handle == NULL)
    {
      sprintf(pathname, "%s/%s.%s", "./", name, EXTENSION);
      handle = dlopen(pathname, RTLD_LAZY);
    }
  if (handle == NULL)
    {
      sprintf(pathname, "%s/lib/%s.%s", GRDIR, name, EXTENSION);
      handle = dlopen(pathname, RTLD_LAZY);
    }
#endif

  if (handle != NULL)
    {
      sprintf(symbol, "gks_%s", name);
#ifdef _WIN32
      entry = GetProcAddress(handle, symbol);
#else
      entry = dlsym(handle, symbol);
#endif
      if (entry == NULL)
	{
#ifdef _WIN32
	  gks_perror("%s: unresolved symbol", symbol);
#else
	  if ((error = dlerror()) != NULL)
	    gks_perror((char *) error);
#endif
	}
    }
  else
    {
#ifdef _WIN32
      gks_perror("%s: can't load library", pathname);
#else
      if ((error = dlerror()) != NULL)
	gks_perror((char *) error);
#endif
    }

  return entry;
}
예제 #2
0
파일: mac.c 프로젝트: albertocabello/gr
void gks_drv_mac(
  int fctid, int dx, int dy, int dimx, int *ia,
  int lr1, double *r1, int lr2, double *r2, int lc, char *chars, void **ptr)
{
  if (fctid == 2)
  {
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
    gks_perror("Quickdraw is deprecated\nConsider using the Quartz driver");
#else
    gks_perror("Carbon support not compiled in");
#endif
    ia[0] = 0;
  }
}
예제 #3
0
/* load a glyph into the slot and compute bearing */
static FT_Error set_glyph(FT_Face face, FT_UInt codepoint, FT_UInt *previous,
                          FT_Vector *pen, FT_Bool vertical, FT_Matrix *rotation,
                          FT_Vector *bearing, FT_Int halign) {
  FT_Error error;
  FT_UInt glyph_index;

  glyph_index = FT_Get_Char_Index(face, codepoint);
  if (FT_HAS_KERNING(face) && *previous && !vertical && glyph_index) {
    FT_Vector delta;
    FT_Get_Kerning(face, *previous, glyph_index, FT_KERNING_DEFAULT,
                   &delta);
    FT_Vector_Transform(&delta, rotation);
    pen->x += delta.x;
    pen->y += delta.y;
  }
  error = FT_Load_Glyph(face, glyph_index, vertical ?
                        FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT);
  if (error) {
    gks_perror("glyph could not be loaded: %c", codepoint);
    return 1;
  }
  error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
  if (error) {
    gks_perror("glyph could not be rendered: %c", codepoint);
    return 1;
  }
  *previous = glyph_index;

  bearing->x = face->glyph->metrics.horiBearingX;
  bearing->y = 0;
  if (vertical) {
    if (halign == GKS_K_TEXT_HALIGN_RIGHT) {
      bearing->x += face->glyph->metrics.width;
    } else if (halign == GKS_K_TEXT_HALIGN_CENTER) {
      bearing->x += face->glyph->metrics.width / 2;
    }
    if (bearing->x != 0) FT_Vector_Transform(bearing, rotation);
    bearing->x = 64 * face->glyph->bitmap_left - bearing->x;
    bearing->y = 64 * face->glyph->bitmap_top  - bearing->y;
  } else {
    if (bearing->x != 0) FT_Vector_Transform(bearing, rotation);
    pen->x -= bearing->x;
    pen->y -= bearing->y;
    bearing->x = 64 * face->glyph->bitmap_left;
    bearing->y = 64 * face->glyph->bitmap_top;
  }
  return 0;
}
예제 #4
0
파일: mac.c 프로젝트: albertocabello/gr
static
void set_font(int font)
{
  double rad, scale, ux, uy;
  int family, size, angle;
  double width, height, capheight;
  StyleParameter face;
  Str255 name;

  font = abs(font);
  if (font >= 101 && font <= 129)
    font -= 100;
  else if (font >= 1 && font <= 32)
    font = map[font - 1];
  else
    font = 9;

  WC_to_NDC_rel(gkss->chup[0], gkss->chup[1], gkss->cntnr, ux, uy);
  seg_xform_rel(&ux, &uy);

  rad = -atan2(ux, uy);
  angle = (int)(rad * 180 / M_PI + 0.5);
  if (angle < 0) angle += 360;
  p->path = ((angle + 45) / 90) % 4;

  scale = sqrt(gkss->chup[0] * gkss->chup[0] + gkss->chup[1] * gkss->chup[1]);
  ux = gkss->chup[0] / scale * gkss->chh;
  uy = gkss->chup[1] / scale * gkss->chh;
  WC_to_NDC_rel(ux, uy, gkss->cntnr, ux, uy);

  width = 0;
  height = sqrt(ux * ux + uy * uy);
  seg_xform_rel(&width, &height);

  height = sqrt(width * width + height * height);
  capheight = nint(height * (fabs(p->c) + 1));
  p->capheight = nint(capheight);

  size = nint(capheight / capheights[font - 1]);
  if (font > 13)
    font += 3;
  p->family = (font - 1) / 4;
  face = (font % 4 == 1 || font % 4 == 2) ? normal : bold;
  if (font % 4 == 2 || font % 4 == 0)
    face |= italic;

  CopyCStringToPascal(fonts[p->family], name);
  family = FMGetFontFamilyFromName(name);
  if (family != kInvalidFontFamily)
    {
      TextFont(family);
      TextFace(face);
      TextSize(size);
    }
  else
    gks_perror("invalid font family (%s)", fonts[p->family]);
}
예제 #5
0
/* set text string, converting UTF-8 into Unicode */
static
void utf_to_unicode(FT_Bytes str, FT_UInt *unicode_string, int *length) {
  FT_UInt num_glyphs = 0;
  FT_UInt codepoint;
  FT_Byte following_bytes;
  FT_Byte offset;
  int i, j;

  for (i = 0; i < *length; i++) {
    if (str[i] < 128) {
      offset = 0;
      following_bytes = 0;
    } else if (str[i] < 128+64+32) {
      offset = 128+64;
      following_bytes = 1;
    } else if (str[i] < 128+64+32+16) {
      offset = 128+64+32;
      following_bytes = 2;
    } else if (str[i] < 128+64+32+16+8) {
      offset = 128+64+32+16;
      following_bytes = 3;
    } else {
      gks_perror("character ignored due to unicode error");
      continue;
    }
    codepoint = str[i] - offset;
    for (j = 0; j < following_bytes; j++) {
      codepoint = codepoint * 64;
      i++;
      if (str[i] < 128 || str[i] >= 128+64) {
        gks_perror("character ignored due to unicode error");
        continue;
      }
      codepoint += str[i] - 128;
    }
    unicode_string[num_glyphs] = codepoint;
    num_glyphs++;
  }
  unicode_string[num_glyphs] = '\0';

  *length = num_glyphs;
}
예제 #6
0
int gks_ft_init(void) {
  FT_Error error;
  if (init) return 0;
  error = FT_Init_FreeType(&library);
  if (error) {
    gks_perror("could not initialize freetype library");
    init = 0;
  } else {
    init = 1;
  }
  return error;
}
예제 #7
0
static FT_Pointer safe_realloc(FT_Pointer ptr, size_t size) {
  FT_Pointer tmp;
  if (ptr) {
    tmp = malloc(size);
  } else {
    tmp = realloc(ptr, size);
  }
  if (tmp != NULL) {
    ptr = tmp;
  } else {
    gks_perror("out of memory");
    ptr = NULL;
  }
  return ptr;
}
예제 #8
0
파일: plugin.c 프로젝트: jheinen/gr
static void *load_library(const char *name)
{
  char pathname[MAXPATHLEN], symbol[255];
#ifdef _WIN32
  HINSTANCE handle;
  LPCTSTR grdir;
  char grbin[MAXPATHLEN];
#else
  void *handle;
  const char *grdir, *error;
#endif
  void *entry = NULL;

  sprintf(pathname, "%s.%s", name, EXTENSION);
#ifdef _WIN32
  handle = LoadLibrary(pathname);
  if (handle == NULL)
    {
      grdir = gks_getenv("GRDIR");
      if (grdir == NULL) grdir = GRDIR;
      sprintf(grbin, "%s/bin", grdir);
      SetDllDirectory(grbin);
      handle = LoadLibrary(pathname);
    }
#else
  handle = dlopen(pathname, RTLD_LAZY);
  if (handle == NULL)
    {
      sprintf(pathname, "%s/%s.%s", "./", name, EXTENSION);
      handle = dlopen(pathname, RTLD_LAZY);
    }
  if (handle == NULL)
    {
      grdir = gks_getenv("GRDIR");
      if (grdir == NULL) grdir = GRDIR;
      sprintf(pathname, "%s/lib/%s.%s", grdir, name, EXTENSION);
      handle = dlopen(pathname, RTLD_LAZY);
    }
#endif

  if (handle != NULL)
    {
      sprintf(symbol, "gks_%s", name);
#ifdef _WIN32
      entry = (void *)GetProcAddress(handle, symbol);
#else
      entry = dlsym(handle, symbol);
#endif
      if (entry == NULL)
        {
#ifdef _WIN32
          gks_perror("%s: unresolved symbol", symbol);
#else
          if ((error = dlerror()) != NULL) gks_perror((char *)error);
#endif
        }
    }
  else
    {
#ifdef _WIN32
      DWORD ec = 0;
      ec = GetLastError();
      gks_perror("%s: can't load library, error %d (0x%x)", pathname, ec, ec);
#else
      if ((error = dlerror()) != NULL) gks_perror((char *)error);
#endif
    }

  return entry;
}
예제 #9
0
파일: socket.c 프로젝트: jheinen/gr
void gks_drv_socket(int fctid, int dx, int dy, int dimx, int *ia, int lr1, double *r1, int lr2, double *r2, int lc,
                    char *chars, void **ptr)
{
  ws_state_list *wss;
  const char *command = NULL, *env;
  int retry_count;
  char *cmd = NULL;

  wss = (ws_state_list *)*ptr;

  switch (fctid)
    {
    case 2:
      gkss = (gks_state_list_t *)*ptr;
      wss = (ws_state_list *)gks_malloc(sizeof(ws_state_list));

      if (ia[2] == 411)
        {
          command = gks_getenv("GKS_QT");
          if (command == NULL)
            {
              env = gks_getenv("GRDIR");
              if (env == NULL) env = GRDIR;

              cmd = (char *)gks_malloc(MAXPATHLEN);
#ifndef _WIN32
#ifdef __APPLE__
              sprintf(cmd, "%s/Applications/gksqt.app/Contents/MacOS/gksqt", env);
#else
              sprintf(cmd, "%s/bin/gksqt", env);
#endif
#else
              sprintf(cmd, "%s\\bin\\gksqt.exe", env);
#endif
              command = cmd;
            }
        }

      for (retry_count = 1; retry_count <= 10; retry_count++)
        {
          if ((wss->s = connect_socket(retry_count != 10)) == -1)
            {
              if (command != NULL && retry_count == 1)
                {
                  if (start(command) != 0) gks_perror("could not auto-start GKS Qt application");
                }
#ifndef _WIN32
              usleep(300000);
#else
              Sleep(300);
#endif
            }
          else
            break;
        }

      if (cmd != NULL) free(cmd);

      if (wss->s == -1)
        {
          gks_perror("can't connect to GKS socket application\n"
                     "Did you start 'gksqt'?\n");

          gks_free(wss);
          wss = NULL;

          ia[0] = ia[1] = 0;
        }
      else
        *ptr = wss;
      break;

    case 3:
      close_socket(wss->s);
      if (wss->dl.buffer)
        {
          free(wss->dl.buffer);
        }
      gks_free(wss);
      wss = NULL;
      break;

    case 8:
      if (ia[1] & GKS_K_PERFORM_FLAG)
        {
          send_socket(wss->s, (char *)&wss->dl.nbytes, sizeof(int));
          send_socket(wss->s, wss->dl.buffer, wss->dl.nbytes);
        }
      break;
    }

  if (wss != NULL)
    {
      gks_dl_write_item(&wss->dl, fctid, dx, dy, dimx, ia, lr1, r1, lr2, r2, lc, chars, gkss);
    }
}
예제 #10
0
int gks_ft_init(void)
{
  gks_perror("FreeType support not compiled in");
  init = 1;
  return 1;
}
예제 #11
0
unsigned char *gks_ft_get_bitmap(int *x, int *y, int *width, int *height,
                                 gks_state_list_t *gkss, const char *text,
                                 int length) {
  FT_Face face;                   /* font face */
  FT_Vector pen;                  /* glyph position */
  FT_BBox bb;                     /* bounding box */
  FT_Vector bearing;              /* individual glyph translation */
  FT_UInt previous;               /* previous glyph index */
  FT_Vector spacing;              /* amount of additional space between glyphs */
  FT_ULong textheight;            /* textheight in FreeType convention */
  FT_Error error;                 /* error code */
  FT_Matrix rotation;             /* text rotation matrix */
  FT_UInt size;                   /* number of pixels of the bitmap */
  FT_String *file;                /* concatenated font path */
  const FT_String *font, *prefix; /* font file name and directory */
  FT_UInt *unicode_string;        /* unicode text string */
  FT_Int halign, valign;          /* alignment */
  FT_Byte *mono_bitmap = NULL;    /* target for rendered text */
  FT_Int num_glyphs;              /* number of glyphs */
  FT_Vector align;
  FT_Bitmap ftbitmap;
  FT_UInt codepoint;
  int i, textfont, dx, dy, value, pos_x, pos_y;
  unsigned int j, k;
  double angle;
  const int windowwidth = *width;
  const int direction = (gkss->txp <= 3 && gkss->txp >= 0 ? gkss->txp : 0);
  const FT_Bool vertical = (direction == GKS_K_TEXT_PATH_DOWN ||
                            direction == GKS_K_TEXT_PATH_UP);
  const FT_String *suffix_type1 = ".afm";

  if (!init) gks_ft_init();

  if (gkss->txal[0] != GKS_K_TEXT_HALIGN_NORMAL) {
    halign = gkss->txal[0];
  } else if (vertical) {
    halign = GKS_K_TEXT_HALIGN_CENTER;
  } else if (direction == GKS_K_TEXT_PATH_LEFT) {
    halign = GKS_K_TEXT_HALIGN_RIGHT;
  } else {
    halign = GKS_K_TEXT_HALIGN_LEFT;
  }
  valign = gkss->txal[1];
  if (valign != GKS_K_TEXT_VALIGN_NORMAL) {
    valign = gkss->txal[1];
  } else {
    valign = GKS_K_TEXT_VALIGN_BASE;
  }

  textfont = abs(gkss->txfont);
  if (textfont >= 101 && textfont <= 131)
    textfont -= 100;
  else if (textfont > 1 && textfont <= 32)
    textfont = map[textfont - 1];
  else
    textfont = 9;

  textfont = textfont - 1;
  font = gks_font_list[textfont];

  if (font_face_cache[textfont] == NULL) {
    prefix = gks_getenv("GKS_FONTPATH");
    if (prefix == NULL) {
      prefix = gks_getenv("GRDIR");
      if (prefix == NULL)
        prefix = GRDIR;
    }
    file = (FT_String *) malloc(strlen(prefix) + 7 + strlen(font) + 4 + 1);
    strcpy(file, prefix);
#ifndef _WIN32
    strcat(file, "/fonts/");
#else
    strcat(file, "\\FONTS\\");
#endif
    strcat(file, font);
    strcat(file, ".pfb");
    error = FT_New_Face(library, file, 0, &face);
    if (error == FT_Err_Unknown_File_Format) {
      gks_perror("unknown file format: %s", file);
      return NULL;
    } else if (error) {
      gks_perror("could not open font file: %s", file);
      return NULL;
    }
    if (strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0) {
      strcpy(file, prefix);
#ifndef _WIN32
      strcat(file, "/fonts/");
#else
      strcat(file, "\\FONTS\\");
#endif
      strcat(file, font);
      strcat(file, suffix_type1);
      FT_Attach_File(face, file);
    }
    free(file);
    font_face_cache[textfont] = face;
  } else {
    face = font_face_cache[textfont];
  }

  num_glyphs = length;
  unicode_string = (FT_UInt *) malloc(length * sizeof(FT_UInt) + 1);
  if (textfont + 1 == 13) {
    symbol_to_unicode((FT_Bytes)text, unicode_string, num_glyphs);
  } else {
    utf_to_unicode((FT_Bytes)text, unicode_string, &num_glyphs);
  }

  textheight = nint(gkss->chh * windowwidth * 64 / caps[textfont]);
  error = FT_Set_Char_Size(face, nint(textheight * gkss->chxp), textheight,
                           72, 72);
  if (error) gks_perror("cannot set text height");

  if (gkss->chup[0] != 0.0 || gkss->chup[1] != 0.0) {
    angle = atan2f(gkss->chup[1], gkss->chup[0]) - M_PI / 2;
    rotation.xx = nint( cosf(angle) * 0x10000L);
    rotation.xy = nint(-sinf(angle) * 0x10000L);
    rotation.yx = nint( sinf(angle) * 0x10000L);
    rotation.yy = nint( cosf(angle) * 0x10000L);
    FT_Set_Transform(face, &rotation, NULL);
  } else {
    FT_Set_Transform(face, NULL, NULL);
  }

  spacing.x = spacing.y = 0;
  if (gkss->chsp != 0.0) {
    error = FT_Load_Glyph(face, FT_Get_Char_Index(face, ' '),
                          vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT);
    if (!error) {
      spacing.x = nint(face->glyph->advance.x * gkss->chsp);
      spacing.y = nint(face->glyph->advance.y * gkss->chsp);
    } else {
      gks_perror("cannot apply character spacing");
    }
  }

  bb.xMin = bb.yMin = LONG_MAX;
  bb.xMax = bb.yMax = LONG_MIN;
  pen.x = pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    bb.xMin = ft_min(bb.xMin, pen.x + bearing.x);
    bb.xMax = ft_max(bb.xMax, pen.x + bearing.x + 64*face->glyph->bitmap.width);
    bb.yMin = ft_min(bb.yMin, pen.y + bearing.y - 64*face->glyph->bitmap.rows);
    bb.yMax = ft_max(bb.yMax, pen.y + bearing.y);

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  *width  = (int)((bb.xMax - bb.xMin) / 64);
  *height = (int)((bb.yMax - bb.yMin) / 64);
  if (bb.xMax <= bb.xMin || bb.yMax <= bb.yMin) {
    gks_perror("invalid bitmap size");
    free(unicode_string);
    return NULL;
  }
  size = *width * *height;
  mono_bitmap = (FT_Byte *) safe_realloc(mono_bitmap, size);
  memset(mono_bitmap, 0, size);

  pen.x = 0;
  pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    bearing.x = bearing.y = 0;
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    pos_x = ( pen.x + bearing.x - bb.xMin) / 64;
    pos_y = (-pen.y - bearing.y + bb.yMax) / 64;
    ftbitmap = face->glyph->bitmap;
    for (j = 0; j < (unsigned int) ftbitmap.rows; j++) {
      for (k = 0; k < (unsigned int) ftbitmap.width; k++) {
        dx = k + pos_x;
        dy = j + pos_y;
        value = mono_bitmap[dy * *width + dx];
        value += ftbitmap.buffer[j * ftbitmap.pitch + k];
        if (value > 255) {
          value = 255;
        }
        mono_bitmap[dy * *width + dx] = value;
      }
    }

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  free(unicode_string);

  /* Alignment */
  if (direction == GKS_K_TEXT_PATH_DOWN) {
    pen.x += spacing.x;
    pen.y += spacing.y;
  } else {
    pen.x -= spacing.x;
    pen.y -= spacing.y;
  }

  align.x = align.y = 0;
  if (valign != GKS_K_TEXT_VALIGN_BASE) {
    align.y = nint(gkss->chh * windowwidth * 64);
    FT_Vector_Transform(&align, &rotation);
    if (valign == GKS_K_TEXT_VALIGN_HALF) {
      align.x = nint(0.5 * align.x);
      align.y = nint(0.5 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_TOP) {
      align.x = nint(1.2 * align.x);
      align.y = nint(1.2 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_BOTTOM) {
      align.x = nint(-0.2 * align.x);
      align.y = nint(-0.2 * align.y);
    }
  }

  if (!vertical && halign != GKS_K_TEXT_HALIGN_LEFT) {
    FT_Vector right;
    right.x = face->glyph->metrics.width + face->glyph->metrics.horiBearingX;
    right.y = 0;
    if (right.x != 0) {
      FT_Vector_Transform(&right, &rotation);
    }
    pen.x += right.x - face->glyph->advance.x;
    pen.y += right.y - face->glyph->advance.y;
    if (halign == GKS_K_TEXT_HALIGN_CENTER) {
      align.x += pen.x / 2;
      align.y += pen.y / 2;
    } else if (halign == GKS_K_TEXT_HALIGN_RIGHT) {
      align.x += pen.x;
      align.y += pen.y;
    }
  }

  *x += (bb.xMin - align.x) / 64;
  *y += (bb.yMin - align.y) / 64;
  return mono_bitmap;
}
예제 #12
0
파일: error.c 프로젝트: j-fu/gr
void gks_fatal_error(const char *args, ...)
{
  gks_perror(args);
  exit(-1);
}
예제 #13
0
파일: error.c 프로젝트: j-fu/gr
void gks_report_error(int routine, int errnum)
{
  const char *name, *message;

  name = gks_function_name(routine);

  switch (errnum)
    {
    case   0: message = "normal successful completion"; break;
    case   1: message = "GKS not in proper state. GKS must be in the state\
 GKCL in routine %s"; break;
    case   2: message = "GKS not in proper state. GKS must be in the state\
 GKOP in routine %s"; break;
    case   3: message = "GKS not in proper state. GKS must be in the state\
 WSAC in routine %s"; break;
    case   4: message =	"GKS not in proper state. GKS must be in the state\
 SGOP in routine %s"; break;
    case   5: message =	"GKS not in proper state. GKS must be either in the\
 state WSAC or SGOP in routine %s"; break;
    case   6: message = "GKS not in proper state. GKS must be either in the\
 state WSOP or WSAC in routine %s"; break;
    case   7: message = "GKS not in proper state. GKS must be in one of the\
 states WSOP,WSAC,SGOP in routine %s"; break;
    case   8: message = "GKS not in proper state. GKS must be in one of the\
 states GKOP,WSOP,WSAC,SGOP in routine %s"; break;
    case  20: message = "Specified workstation identifier is invalid in\
 routine %s"; break;
    case  21: message = "Specified connection identifier is invalid in\
 routine %s"; break;
    case  22: message = "Specified workstation type is invalid in\
 routine %s"; break;
    case  24: message = "Specified workstation is open in routine %s"; break;
    case  25: message = "Specified workstation is not open in\
 routine %s"; break;
    case  26: message = "Specified workstation cannot be opened in\
 routine %s"; break;
    case  27: message =	"Workstation Independent Segment Storage is\
 not open in routine %s"; break;
    case  28: message = "Workstation Independent Segment Storage is\
 already open in routine %s"; break;
    case  29: message = "Specified workstation is active in routine %s"; break;
    case  30: message = "Specified workstation is not active in\
 routine %s"; break;
    case  34: message = "Specified workstation is not of category MI in\
 routine %s"; break;
    case  38: message = "Specified workstation is neither of category INPUT\
 nor of category OUTIN in routine %s"; break;
    case  50: message = "Transformation number is invalid in routine %s"; break;
    case  51: message = "Rectangle definition is invalid in routine %s"; break;
    case  52: message = "Viewport is not within the NDC unit square in\
 routine %s"; break;
    case  53: message = "Workstation window is not within the NDC unit square\
 in routine %s"; break;
    case  60: message = "Polyline index is invalid in routine %s"; break;
    case  62: message = "Linetype is invalid in routine %s"; break;
    case  64: message = "Polymarker index is invalid in routine %s"; break;
    case  65: message = "Colour index is invalid in routine %s"; break;
    case  66: message = "Marker type is invalid in routine %s"; break;
    case  68: message = "Text index is invalid in routine %s"; break;
    case  70: message = "Text font is invalid in routine %s"; break;
    case  72: message = "Character expansion factor is invalid in\
 routine %s"; break;
    case  73: message = "Character height is invalid in routine %s"; break;
    case  74: message = "Character up vector is invalid in routine %s"; break;
    case  75: message = "Fill area index is invalid in routine %s"; break;
    case  78: message = "Style index is invalid in routine %s"; break;
    case  81: message = "Pattern size value is invalid in routine %s"; break;
    case  84: message = "Dimensions of colour index array are invalid in\
 routine %s"; break;
    case  85: message = "Colour index is invalid in routine %s"; break;
    case  88: message = "Colour is invalid in routine %s"; break;
    case  91: message = "Dimensions of color index array are invalid in\
 routine %s"; break;
    case 100: message = "Number of points is invalid in routine %s"; break;
    case 161: message = "Item length is invalid in routine %s"; break;
    case 163: message = "Metafile item is invalid in routine %s"; break;
    case 164: message = "Item type is not a valid GKS item in\
 routine %s"; break;
    case 401: message = "Dimensions of image are invalid in routine %s"; break;
    case 402: message = "Invalid image data pointer in routine %s"; break;
    case 403: message = "String is too long in routine %s"; break;
    case 404: message = "Subimage limitation reached in routine %s"; break;
    case 901: message = "Open failed in routine %s"; break;
     default: message = "unknown error";
    }

  gks_errno = errnum;

  gks_perror(message, name);
}