Пример #1
0
static void Resize (XtcwpAxesWidget w)
{
    XtcwpAxesCallbackStruct cb;
    XFontStruct *fa,*ft;
    XCharStruct cs;
    int labelch,labelcw,titlech,bl,bt,br,bb,ticsize,dummy;

    /* get fonts and determine character dimensions */
    fa = XQueryFont(XtDisplay(w),w->axes.labelfont);
    XTextExtents(fa,"2",1,&dummy,&dummy,&dummy,&cs);
    labelch = cs.ascent+cs.descent;
    labelcw = cs.width;
    ft = XQueryFont(XtDisplay(w),w->axes.titlefont);
    titlech = ft->max_bounds.ascent+ft->max_bounds.descent;

    /* determine axes rectangle position and dimensions */
    ticsize = labelcw;
    bl = labelch+7*labelcw;
    br = w->core.width-5*labelcw;
    while (br<bl) {
        br += labelcw;
        bl -= labelcw;
    }
    if (bl<0) bl = 0;
    if (br>((int) w->core.width)) br = w->core.width;
    if (w->axes.style==XtcwpNORMAL) {
        bt = labelch+labelch/2+titlech;
        bb = w->core.height-3*ticsize/2-2*labelch;
    } else {
        bt = 3*ticsize/2+2*labelch;
        bb = w->core.height-labelch-labelch/2-titlech;
    }
    while (bb<bt) {
        bb += labelch;
        bt -= labelch;
    }
    if (bt<0) bt = 0;
    if (bb>((int) w->core.height)) bb = w->core.height;
    w->axes.x = bl;
    w->axes.y = bt;
    w->axes.width = br-bl;
    w->axes.height = bb-bt;

    /* Free font info */
    XFreeFontInfo(NULL,fa,1);
    XFreeFontInfo(NULL,ft,1);

    /* call callbacks */
    fillCallbackStruct(w,XtcwpCR_RESIZE,NULL,NULL,&cb);
    XtCallCallbacks ((Widget) w,XtNresizeCallback,&cb);
}
Пример #2
0
PetscErrorCode XiInitFonts(PetscDraw_X *XBWin)
{
  char         **names;
  int          cnt,i,j;
  XFontStruct  *info;

  PetscFunctionBegin;
  /* This just gets the most basic fixed-width fonts */
  names   = XListFontsWithInfo(XBWin->disp,"?x??",NFONTS,&cnt,&info);
  j       = 0;
  for (i=0; i<cnt; i++) {
    names[i][1]         = '\0';
    nfonts[j].w         = info[i].max_bounds.width ;
    nfonts[j].h         = info[i].ascent + info[i].descent;
    nfonts[j].descent   = info[i].descent;
    if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
    j++;
    if (j >= NFONTS) break;
  }
  act_nfonts    = j;
  if (cnt > 0)  {
    XFreeFontInfo(names,info,cnt);
  }
  /* If the above fails,try this: */
  if (!act_nfonts) {
    /* This just gets the most basic fixed-width fonts */
    names   = XListFontsWithInfo(XBWin->disp,"?x",NFONTS,&cnt,&info);
    j       = 0;
    for (i=0; i<cnt; i++) {
        PetscErrorCode ierr;
        size_t len;

        ierr = PetscStrlen(names[i],&len);CHKERRQ(ierr);
        if (len != 2) continue;
        names[i][1]         = '\0';
	nfonts[j].w         = info[i].max_bounds.width ;
        /* nfonts[j].w         = info[i].max_bounds.lbearing +
                                    info[i].max_bounds.rbearing; */
        nfonts[j].h         = info[i].ascent + info[i].descent;
        nfonts[j].descent   = info[i].descent;
        if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue;
        j++;
	if (j >= NFONTS) break;
    }
    act_nfonts    = j;
    XFreeFontInfo(names,info,cnt);
  }
  PetscFunctionReturn(0);
}
Пример #3
0
static void
Dealloc(PaxFontObject *self)
{
    if (self->from_id)
	XFreeFontInfo(NULL, self->font_struct, 1);
    else
	XFreeFont(self->display, self->font_struct);
    PyObject_Del(self);
}
Пример #4
0
static
void get_list(char *pattern)
{
    int           available = nnames+1,
                  i;
    char        **fonts;
    XFontStruct  *info;

    /* Get list of fonts matching pattern */
    for (;;) {
        if (open_instead_of_list) {
            info = XLoadQueryFont (dpy, pattern);

            if (info) {
                fonts = &pattern;
                available = 1;
                XUnloadFont (dpy, info->fid);
            } else {
                fonts = NULL;
            }
            break;
        }
            
        if (long_list == L_MEDIUM)
            fonts = XListFontsWithInfo(dpy, pattern, nnames, &available, &info);
        else
            fonts = XListFonts(dpy, pattern, nnames, &available);
        if (fonts == NULL || available < nnames)
            break;
        if (long_list == L_MEDIUM)
            XFreeFontInfo(fonts, info, available);
        else
            XFreeFontNames(fonts);
        nnames = available * 2;
    }

    if (fonts == NULL) {
        fprintf(stderr, "%s: pattern \"%s\" unmatched\n",
                program_name, pattern);
        return;
    }

    font_list = (FontList *)Realloc((char *)font_list,
            (font_cnt + available) * sizeof(FontList));
    for (i=0; i<available; i++) {
        font_list[font_cnt].name = fonts[i];
        if (long_list == L_MEDIUM)
            font_list[font_cnt].info = info + i;
        else
            font_list[font_cnt].info = NULL;
        
        font_cnt++;
    }
}
Пример #5
0
static int init_xfont(void)
{
    XFontStruct  *xfs;

	xfs = find_font(XFixedFontList, NULL);
	if (xfs == NULL) {
  	  fprintf(stderr, "Could not load fixed font");
      return 0;
	}	  

	if (FontName[FT_FIXED]) XFree(FontName[FT_FIXED]);
    FontName[FT_FIXED] = get_font_name(xfs);        
	
    FontId[FT_FIXED] = xfs->fid;
    FixedFontAscent = xfs->ascent;
    FixedFontDescent = xfs->descent;
    FixedFontWidth = (xfs->min_bounds).width;
    FontHeight[FT_FIXED] = FixedFontAscent + FixedFontDescent;
	XFreeFontInfo(NULL, xfs, 1);


	xfs = find_font(XVarFontList, NULL);
	if (FontName[FT_VAR]) XFree(FontName[FT_VAR]);
	if (xfs == NULL)
	{
	  fprintf(stderr, "Unable to load variable font - fixed font will be used");
	  FontName[FT_VAR] = strdup(FontName[FT_FIXED]);
	  FontId[FT_VAR] = FontId[FT_FIXED];	  
	}	  
	else
	{
	  FontName[FT_VAR] = get_font_name(xfs);
	  FontHeight[FT_VAR] = xfs->ascent + xfs->descent;
	  FontId[FT_VAR] = xfs->fid;
	  XFreeFontInfo(NULL, xfs, 1);
	}

    return 1;

}
Пример #6
0
static int query_font_geometry (Display *dpy, GC gc, const char *txt, int *w, int *h, int *a, int *d) {
	XCharStruct text_structure;
	int font_direction, font_ascent, font_descent;
	XFontStruct *fontinfo = XQueryFont (dpy, XGContextFromGC (gc));

	if (!fontinfo) { return -1; }
	XTextExtents (fontinfo, txt, strlen (txt), &font_direction, &font_ascent, &font_descent, &text_structure);
	if (w) *w = XTextWidth (fontinfo, txt, strlen (txt));
	if (h) *h = text_structure.ascent + text_structure.descent;
	if (a) *a = text_structure.ascent;
	if (d) *d = text_structure.descent;
	XFreeFontInfo (NULL, fontinfo, 1);
	return 0;
}
Пример #7
0
static
void do_query_font (Display *dpy, char *name)
{
    register int i;
    register XFontStruct *info = XLoadQueryFont (dpy, name);

    if (!info) {
        fprintf (stderr, "%s:  unable to get info about font \"%s\"\n",
                 program_name, name);
        return;
    }
    printf ("name:  %s\n", name ? name : "(nil)");
    printf ("  direction:\t\t%s\n", ((info->direction == FontLeftToRight)
                                     ? "left to right" : "right to left"));
    printf ("  indexing:\t\t%s\n", 
            ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" :
             "matrix"));
    printf ("  rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n",
            info->min_byte1, info->max_byte1,
            info->min_byte1, info->max_byte1);
    printf ("  columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n",
            info->min_char_or_byte2, info->max_char_or_byte2,
            info->min_char_or_byte2, info->max_char_or_byte2);
    printf ("  all chars exist:\t%s\n",
        (info->all_chars_exist) ? "yes" : "no");
    printf ("  default char:\t\t0x%04x (%d)\n",
            info->default_char, info->default_char);
    printf ("  ascent:\t\t%d\n", info->ascent);
    printf ("  descent:\t\t%d\n", info->descent);
    ComputeFontType (info);
    printf ("  bounds:\t\t%s", bounds_metrics_title);
    PrintBounds ("min", &info->min_bounds);
    PrintBounds ("max", &info->max_bounds);
    if (info->per_char && long_list >= L_VERYLONG) 
        print_character_metrics (info);
    printf ("  properties:\t\t%d\n", info->n_properties);
    for (i = 0; i < info->n_properties; i++)
        PrintProperty (&info->properties[i]);
    printf ("\n");

    XFreeFontInfo (NULL, info, 1);
}
Пример #8
0
PetscErrorCode XiLoadFont(PetscDraw_X *XBWin,XiFont *font)
{
  char        font_name[100];
  XFontStruct *FontInfo;
  XGCValues   values ;

  PetscFunctionBegin;
  (void) sprintf(font_name,"%dx%d",font->font_w,font->font_h);
  font->fnt  = XLoadFont(XBWin->disp,font_name);

  /* The font->descent may not have been set correctly; get it now that
      the font has been loaded */
  FontInfo   = XQueryFont(XBWin->disp,font->fnt);
  font->font_descent   = FontInfo->descent;

  XFreeFontInfo(0,FontInfo,1);

  /* Set the current font in the CG */
  values.font = font->fnt ;
  XChangeGC(XBWin->disp,XBWin->gc.set,GCFont,&values); 
  PetscFunctionReturn(0);
}
Пример #9
0
static void
draw_xor_rect (MetaScreen          *screen,
               const MetaRectangle *rect,
               int                  width,
               int                  height)
{
  /* The lines in the center can't overlap the rectangle or each
   * other, or the XOR gets reversed. So we have to draw things
   * a bit oddly.
   */
  XSegment segments[8];
  MetaRectangle shrunk_rect;
  int i;

#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH

  /* We don't want the wireframe going outside the window area.
   * It makes it harder for the user to position windows and it exposes other
   * annoying bugs.
   */
  shrunk_rect = *rect;

  shrunk_rect.x += LINE_WIDTH / 2 + LINE_WIDTH % 2;
  shrunk_rect.y += LINE_WIDTH / 2 + LINE_WIDTH % 2;
  shrunk_rect.width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
  shrunk_rect.height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);

  XDrawRectangle (screen->display->xdisplay,
                  screen->xroot,
                  screen->root_xor_gc,
                  shrunk_rect.x, shrunk_rect.y,
                  shrunk_rect.width, shrunk_rect.height);

  /* Don't put lines inside small rectangles where they won't fit */
  if (shrunk_rect.width < (LINE_WIDTH * 4) ||
      shrunk_rect.height < (LINE_WIDTH * 4))
    return;

  if ((width >= 0) && (height >= 0))
    {
      XGCValues gc_values = { 0 };

      if (XGetGCValues (screen->display->xdisplay,
                        screen->root_xor_gc,
                        GCFont, &gc_values))
        {
          char *text;
          int text_length;

          XFontStruct *font_struct;
          int text_width, text_height;
          int box_x, box_y;
          int box_width, box_height;

          font_struct = XQueryFont (screen->display->xdisplay,
                                    gc_values.font);

          if (font_struct != NULL)
            {
              text = g_strdup_printf ("%d x %d", width, height);
              text_length = strlen (text);

              text_width = text_length * font_struct->max_bounds.width;
              text_height = font_struct->max_bounds.descent +
                            font_struct->max_bounds.ascent;

              box_width = text_width + 2 * LINE_WIDTH;
              box_height = text_height + 2 * LINE_WIDTH;


              box_x = shrunk_rect.x + (shrunk_rect.width - box_width) / 2;
              box_y = shrunk_rect.y + (shrunk_rect.height - box_height) / 2;

              if ((box_width < shrunk_rect.width) &&
                  (box_height < shrunk_rect.height))
                {
                  XFillRectangle (screen->display->xdisplay,
                                  screen->xroot,
                                  screen->root_xor_gc,
                                  box_x, box_y,
                                  box_width, box_height);
                  XDrawString (screen->display->xdisplay,
                               screen->xroot,
                               screen->root_xor_gc,
                               box_x + LINE_WIDTH,
                               box_y + LINE_WIDTH + font_struct->max_bounds.ascent,
                               text, text_length);
                }

              g_free (text);

              XFreeFontInfo (NULL, font_struct, 1);

              if ((box_width + LINE_WIDTH) >= (shrunk_rect.width / 3))
                return;

              if ((box_height + LINE_WIDTH) >= (shrunk_rect.height / 3))
                return;
            }
        }
    }

  /* Two vertical lines at 1/3 and 2/3 */
  segments[0].x1 = shrunk_rect.x + shrunk_rect.width / 3;
  segments[0].y1 = shrunk_rect.y + LINE_WIDTH / 2 + LINE_WIDTH % 2;
  segments[0].x2 = segments[0].x1;
  segments[0].y2 = shrunk_rect.y + shrunk_rect.height - LINE_WIDTH / 2;

  segments[1] = segments[0];
  segments[1].x1 = shrunk_rect.x + (shrunk_rect.width / 3) * 2;
  segments[1].x2 = segments[1].x1;

  /* Now make two horizontal lines at 1/3 and 2/3, but not
   * overlapping the verticals
   */

  segments[2].x1 = shrunk_rect.x + LINE_WIDTH / 2 + LINE_WIDTH % 2;
  segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2;
  segments[2].y1 = shrunk_rect.y + shrunk_rect.height / 3;
  segments[2].y2 = segments[2].y1;

  segments[3] = segments[2];
  segments[3].x1 = segments[2].x2 + LINE_WIDTH;
  segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2;

  segments[4] = segments[3];
  segments[4].x1 = segments[3].x2 + LINE_WIDTH;
  segments[4].x2 = shrunk_rect.x + shrunk_rect.width - LINE_WIDTH / 2;

  /* Second horizontal line is just like the first, but
   * shifted down
   */
  i = 5;
  while (i < 8)
    {
      segments[i] = segments[i - 3];
      segments[i].y1 = shrunk_rect.y + (shrunk_rect.height / 3) * 2;
      segments[i].y2 = segments[i].y1;
      ++i;
    }

  XDrawSegments (screen->display->xdisplay,
                 screen->xroot,
                 screen->root_xor_gc,
                 segments,
                 G_N_ELEMENTS (segments));
}
Пример #10
0
main()
{
      Window w2;

      Display *dpy = XOpenDisplay(NIL);
      assert(dpy);
      Screen *scr = DefaultScreenOfDisplay(dpy);

      // CreateWindow

      Window w = XCreateWindow(dpy, RootWindowOfScreen(scr), 10, 100, 200, 300, 0, CopyFromParent,
			       CopyFromParent, CopyFromParent,
			       0, NIL);

      XDestroyWindow(dpy, w);

      // CreateWindow with arguments

      XSetWindowAttributes swa;
      swa.background_pixel = WhitePixelOfScreen(scr);
      swa.bit_gravity = NorthWestGravity;
      swa.border_pixel = BlackPixelOfScreen(scr);
      swa.colormap = DefaultColormapOfScreen(scr);
      swa.cursor = None;
      swa.win_gravity = NorthGravity;

      w = XCreateWindow(dpy, RootWindowOfScreen(scr), 10, 100, 200, 300, 0, CopyFromParent,
			CopyFromParent, CopyFromParent,
			CWBackPixel | CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWWinGravity, 
			&swa);
      
      // CreateWindow with other arguments

      XDestroyWindow(dpy, w);

      Pixmap pixmap = XCreatePixmap(dpy, RootWindowOfScreen(scr), 45, 25, DefaultDepthOfScreen(scr));
      assert(pixmap);

      swa.background_pixmap = pixmap;
      swa.border_pixmap = pixmap;

      w = XCreateWindow(dpy, RootWindowOfScreen(scr), 10, 100, 200, 300, 0, CopyFromParent,
			CopyFromParent, CopyFromParent,
			CWBackPixmap | CWBorderPixmap,
			&swa);
      
      // ChangeWindowAttributes

      swa.backing_planes = 0x1;
      swa.backing_pixel = WhitePixelOfScreen(scr);
      swa.save_under = True;
      swa.event_mask = KeyPressMask | KeyReleaseMask;
      swa.do_not_propagate_mask = ButtonPressMask | Button4MotionMask;
      swa.override_redirect = False;
      XChangeWindowAttributes(dpy, w, CWBackingPlanes | CWBackingPixel | CWSaveUnder | CWEventMask
			      | CWDontPropagate | CWOverrideRedirect, &swa);

      // GetWindowAttributes

      XWindowAttributes wa;
      Status success = XGetWindowAttributes(dpy, w, &wa);

      // DestroyWindow (done)

      // DestroySubwindows

      w2 = XCreateWindow(dpy, w, 20, 30, 40, 50, 3, CopyFromParent, CopyFromParent, CopyFromParent, 0, NIL);
      XDestroySubwindows(dpy, w);

      // ChangeSaveSet

//        Display *dpy2 = XOpenDisplay(NIL);
//        assert(dpy2);
//        XAddToSaveSet(dpy2, w);
//        XCloseDisplay(dpy2);

      // ReparentWindow

      w2 = XCreateWindow(dpy, RootWindowOfScreen(scr), 20, 30, 40, 50, 3, 
			 CopyFromParent, CopyFromParent, CopyFromParent, 0, NIL);
      XReparentWindow(dpy, w2, w, 10, 5);

      // MapWindow

      XMapWindow(dpy, w);

      // MapSubwindows
      
      XMapSubwindows(dpy, w);

      // UnmapWindow
      
      XUnmapWindow(dpy, w);

      // UnmapSubwindows

      XMapWindow(dpy, w);
      XUnmapSubwindows(dpy, w2);
      XMapSubwindows(dpy, w);

      // ConfigureWindow

      Window w3 = XCreateWindow(dpy, w, 10, 50, 100, 10, 2,
			 CopyFromParent, CopyFromParent, CopyFromParent, 0, NIL);

      XMapWindow(dpy, w3);

      XWindowChanges wc;
      wc.x = -5;
      wc.y = -10;
      wc.width = 50;
      wc.height = 40;
      wc.border_width = 7;
      wc.sibling = w2;
      wc.stack_mode = Opposite;
      XConfigureWindow(dpy, w3, 
		       CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWSibling | CWStackMode, 
		       &wc);

      // CirculateWindow

      XCirculateSubwindows(dpy, w, RaiseLowest);

      // GetGeometry

      Window root;
      int x, y;
      unsigned width, height, border_width, depth;
      XGetGeometry(dpy, w, &root, &x, &y, &width, &height, &border_width, &depth);

      // QueryTree

      Window parent;
      Window *children;
      unsigned nchildren;
      success = XQueryTree(dpy, w, &root, &parent, &children, &nchildren);
      XFree(children);

      // InternAtom

      Atom a = XInternAtom(dpy, "WM_PROTOCOLS", True);

      // GetAtomName

      char *string = XGetAtomName(dpy, XA_PRIMARY);
      XFree(string);

      // ChangeProperty

      XStoreName(dpy, w, "test window");

      // DeleteProperty

      XDeleteProperty(dpy, w, XA_WM_NAME);

      // GetProperty
      // TODO

      // ListProperties

      int num_prop;
      Atom *list = XListProperties(dpy, w, &num_prop);
      XFree(list);

      // SetSelectionOwner

      XSetSelectionOwner(dpy, XA_PRIMARY, w, 12000);
      XSetSelectionOwner(dpy, XA_SECONDARY, w, CurrentTime);

      // GetSelectionOwner

      Window wx = XGetSelectionOwner(dpy, XA_PRIMARY);

      // ConvertSelection

      XConvertSelection(dpy, XA_SECONDARY, XA_CURSOR, XA_POINT, w, CurrentTime);

      // SendEvent

      // GrabPointer

      std::cerr << "Grabbing" << std::endl;
      int res = XGrabPointer(dpy, w, False, Button5MotionMask | PointerMotionHintMask,
			     GrabModeSync, GrabModeAsync, w, None, CurrentTime);
      XSync(dpy, False);
//      sleep(5);

      // UngrabPointer

      std::cerr << "Ungrabbing" << std::endl;
      XUngrabPointer(dpy, CurrentTime);

      // GrabButton

      XGrabButton(dpy, 3, ShiftMask | ControlMask, w, False, PointerMotionHintMask | Button2MotionMask, 
		  GrabModeAsync, GrabModeSync, None, None);
		  
      XGrabButton(dpy, 2, AnyModifier, w, False, PointerMotionHintMask | Button2MotionMask, 
		  GrabModeAsync, GrabModeSync, None, None);
		  
      // UngrabButton

      XUngrabButton(dpy, 2, LockMask, w);

      // ChangeActivePointerGrab

      XChangeActivePointerGrab(dpy, ButtonPressMask, None, CurrentTime);

      // GrabKeyboard

      XGrabKeyboard(dpy, w, True, GrabModeSync, GrabModeSync, 12000);

      // UngrabKeyboard

      XUngrabKeyboard(dpy, 13000);

      // GrabKey

      XGrabKey(dpy, XKeysymToKeycode(dpy, XK_Tab), ShiftMask | Mod3Mask, w, True, GrabModeSync,
	       GrabModeSync);

      // UngrabKey

      XUngrabKey(dpy, AnyKey, AnyModifier, w);

      // AllowEvents

      XAllowEvents(dpy, AsyncPointer, 14000);

      // GrabServer

      XGrabServer(dpy);

      // UngrabServer

      XUngrabServer(dpy);

      // QueryPointer

      Window child;
      int root_x, root_y, win_x, win_y;
      unsigned mask;
      Bool bres = XQueryPointer(dpy, w, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask);

      // GetMotionEvents

      int nevents;
      XGetMotionEvents(dpy, w, 15000, 16000, &nevents);

      // TranslateCoordinates

      int dest_x, dest_y;

      XTranslateCoordinates(dpy, w, w2, 10, 20, &dest_x, &dest_y, &child);

      // WarpPointer

      XWarpPointer(dpy, w, w2, 0, 0, 100, 100, 20, 30);

      // SetInputFocus

      XSetInputFocus(dpy,w, RevertToPointerRoot, 17000);
      XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, 17000);

      // GetInputFocus

      Window focus;
      int revert_to;
      XGetInputFocus(dpy, &focus, &revert_to);

      // QueryKeymap

      char keys_return[32];
      XQueryKeymap(dpy, keys_return);

      // OpenFont

      Font fid = XLoadFont(dpy, "cursor");

      // CloseFont

      XUnloadFont(dpy, fid);

      // QueryFont

      XFontStruct *fs = XLoadQueryFont(dpy, "cursor");
      assert(fs);

      // QueryTextExtents

      int direction, font_ascent, font_descent;
      XCharStruct overall;
      XQueryTextExtents(dpy, fs -> fid, "toto", 4, &direction, &font_ascent, &font_descent, &overall);
      XQueryTextExtents(dpy, fs -> fid, "odd__length", 11, &direction, &font_ascent, &font_descent, &overall);

      XChar2b c2bs;
      c2bs.byte1 = '$';
      c2bs.byte2 = 'B';
      XQueryTextExtents16(dpy, fs -> fid, &c2bs, 1, &direction, &font_ascent, &font_descent, &overall);

      XQueryTextExtents(dpy, fs -> fid, longString, strlen(longString), &direction, &font_ascent, 
			&font_descent, &overall);

      // ListFonts

      int actual_count;
      char **fontList = XListFonts(dpy, "*", 100, &actual_count);
      XFree((char *)fontList);

      // ListFontsWithInfo

      int count;
      XFontStruct *info;
      char **names = XListFontsWithInfo(dpy, "*", 100, &count, &info);
      XFreeFontInfo(names, info, count);

      // SetFontPath
      // GetFontPath

      int npaths;
      char **charList = XGetFontPath(dpy, &npaths);

      char **charList2 = new char *[npaths + 1];
      memcpy(charList2, charList, npaths * sizeof(char *));
      charList2[npaths] = charList2[0];

      XSetFontPath(dpy, charList2, npaths + 1);
      XSetFontPath(dpy, charList, npaths); // Reset to some reasonnable value

      XFreeFontPath(charList);
      delete [] charList2;

      // CreatePixmap

      Pixmap pix2 = XCreatePixmap(dpy, w, 100, 200, DefaultDepthOfScreen(scr));

      // FreePixmap

      XFreePixmap(dpy, pix2);

      // CreateGC

      Pixmap bitmap = XCreateBitmapFromData(dpy, RootWindowOfScreen(scr), 
					    "\000\000\001\000\000\001\000\000\001\377\377\377", 3, 4);

      XGCValues gcv;
      gcv.function = GXand;
      gcv.plane_mask = 0x1;
      gcv.foreground = WhitePixelOfScreen(scr);
      gcv.background = BlackPixelOfScreen(scr);
      gcv.line_width = 2;
      gcv.line_style = LineDoubleDash;
      gcv.cap_style = CapProjecting;
      gcv.join_style = JoinRound;
      gcv.fill_style = FillStippled;
      gcv.fill_rule = EvenOddRule;
      gcv.arc_mode = ArcPieSlice;
      gcv.tile = pixmap;
      gcv.stipple = bitmap;
      gcv.ts_x_origin = 3;
      gcv.ts_y_origin = 4;
      gcv.font = fs -> fid;
      gcv.subwindow_mode = ClipByChildren;
      gcv.graphics_exposures = True;
      gcv.clip_x_origin = 5;
      gcv.clip_y_origin = 6;
      gcv.clip_mask = bitmap;
      gcv.dash_offset = 1;
      gcv.dashes = 0xc2;
      
      GC gc = XCreateGC(dpy, w, 
			  GCFunction | GCPlaneMask | GCForeground | GCBackground | GCLineWidth
			| GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle | GCFillRule | GCTile
			| GCStipple | GCTileStipXOrigin | GCTileStipYOrigin | GCFont | GCSubwindowMode
			| GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin | GCClipMask | GCDashOffset
			| GCDashList | GCArcMode,
			&gcv);

      // ChangeGC

      gcv.function = GXandReverse;

      // Only a few of these should appear, since the values are cached on the client side by the Xlib.

      XChangeGC(dpy, gc, GCFunction | GCLineStyle | GCStipple | GCGraphicsExposures | GCDashList, &gcv);

      // CopyGC
      
      GC gc2 = XCreateGC(dpy, w, 0, NIL);
      XCopyGC(dpy, gc, GCFunction | GCLineStyle | GCStipple | GCGraphicsExposures | GCDashList, gc2);

      // SetDashes

      XSetDashes(dpy, gc, 3, "\001\377\001", 3);

      // SetClipRectangles

      XRectangle rectangles[] = { { 10, 20, 30, 40 }, { 100, 200, 5, 3 }, { -5, 1, 12, 24 } };
      XSetClipRectangles(dpy, gc, 12, 9, rectangles, SIZEOF(rectangles), Unsorted);

      // FreeGC

	    // done already

      // ClearArea

      XClearArea(dpy, w, 30, 10, 10, 100, False);

      // CopyArea

      XCopyArea(dpy, w, pixmap, gc, 0, 0, 100, 100, 10, 10);

      // CopyPlane

      // This won't work if the Screen doesn't have at least 3 planes
      XCopyPlane(dpy, pixmap, w, gc, 20, 10, 40, 30, 0, 0, 0x4);

      // PolyPoint

      XDrawPoint(dpy, w, gc, 1, 2);

      XPoint points[] = { { 3, 4 }, { 5, 6 } };
      XDrawPoints(dpy, w, gc, points, SIZEOF(points), CoordModeOrigin);

      // PolyLine

      XDrawLines(dpy, w, gc, points, SIZEOF(points), CoordModePrevious);

      // PolySegment

      XSegment segments[] = { { 7, 8, 9, 10 }, { 11, 12, 13, 14 }, { 15, 16, 17, 18 } };
      XDrawSegments(dpy, w, gc, segments, SIZEOF(segments));

      // PolyRectangle

      XDrawRectangles(dpy, w, gc, rectangles, SIZEOF(rectangles));

      // PolyArc

      XArc arcs[] = { { 10, 20, 30, 40, 50, 60 }, { -70, 80, 90, 100, 110, 120 }, 
		      { 10, 20, 30, 40, 50, -30 } };

      XDrawArcs(dpy, w, gc, arcs, SIZEOF(arcs));

      // FillPoly

      XFillPolygon(dpy, w, gc, points, SIZEOF(points), Convex, CoordModePrevious);

      // PolyFillRectangle
      
      XFillRectangles(dpy, w, gc, rectangles, SIZEOF(rectangles));

      // PolyFillArc
      
      XFillArcs(dpy, w, gc, arcs, SIZEOF(arcs));

      // PutImage
      // GetImage

      XImage *image = XGetImage(dpy, w, 10, 20, 40, 30, AllPlanes, ZPixmap);
      XPutImage(dpy, w, gc, image, 0, 0, 50, 60, 40, 30);
      XSync(dpy, False); // Make the next request starts at the beginning of a packet

      // PolyText8
      XTextItem textItems[3];
      textItems[0].chars = "toto";
      textItems[0].nchars = strlen(textItems[0].chars);
      textItems[0].delta = -3;
      textItems[0].font = fs->fid;
      textItems[1].chars = "titi";
      textItems[1].nchars = strlen(textItems[1].chars);
      textItems[1].delta = 3;
      textItems[1].font = None;
      textItems[2].chars = "tutu";
      textItems[2].nchars = strlen(textItems[2].chars);
      textItems[2].delta = 0;
      textItems[2].font = fs->fid;

      XDrawText(dpy, w, gc, 10, 10, textItems, 3);


      XTextItem textItems2[3];
      textItems2[0].chars = "totox";
      textItems2[0].nchars = strlen(textItems2[0].chars);
      textItems2[0].delta = -3;
      textItems2[0].font = fs->fid;
      textItems2[1].chars = "titi";
      textItems2[1].nchars = strlen(textItems2[1].chars);
      textItems2[1].delta = 3;
      textItems2[1].font = None;
      textItems2[2].chars = "tutu";
      textItems2[2].nchars = strlen(textItems2[2].chars);
      textItems2[2].delta = 0;
      textItems2[2].font = fs->fid;

      XDrawText(dpy, w, gc, 10, 10, textItems2, 3);

      // PolyText16

      XChar2b c2b2[] = { 0, 't', 0, 'x' };

      XTextItem16 items16[] = { { &c2bs, 1, -5, None }, { NULL, 0, 0, None }, { c2b2, 2, 0, fs -> fid } };
      XDrawText16(dpy, w, gc, 10, 0, items16, SIZEOF(items16));

      // ImageText8

      XDrawImageString(dpy, w, gc, 10, 10, "toto", 4);

      // ImageText16

      XDrawImageString16(dpy, w, gc, 10, 10, &c2bs, 1);
      XDrawImageString16(dpy, w, gc, 10, 20, c2b2, 2);

      // CreateColormap
      // Don't forget to tell the kids how it was when we had only 8 bits per pixel.

      Colormap colormap = XCreateColormap(dpy, w, DefaultVisualOfScreen(scr), None);

      // FreeColormap

      XFreeColormap(dpy, colormap);
      colormap = XCreateColormap(dpy, w, DefaultVisualOfScreen(scr), None);

      // CopyColormapAndFree

      Colormap colormap2 = XCopyColormapAndFree(dpy, colormap);

      // InstallColormap

      XInstallColormap(dpy, colormap2);

      // UninstallColormap

      XUninstallColormap(dpy, colormap2);

      // ListInstalledColormaps

      int num;
      Colormap *colormapList = XListInstalledColormaps(dpy, w, &num);

      // AllocColor

      XColor screen;
      screen.red = 0;
      screen.green = 32767;
      screen.blue = 65535;
      screen.flags = DoRed | DoGreen | DoBlue;
      success = XAllocColor(dpy, colormap, &screen);

      // AllocNamedColor

      XColor screen2, exact;
      success = XAllocNamedColor(dpy, colormap, "Wheat", &screen2, &exact);

      // AllocColorCells

      unsigned long plane_masks, pixels;
      success = XAllocColorCells(dpy, colormap, False, &plane_masks, 1, &pixels, 1);

      // AllocColorPlanes

      unsigned long rmask, gmask, bmask;
      success = XAllocColorPlanes(dpy, colormap, False, &pixels, 1, 0, 0, 0, &rmask, &gmask, &bmask);

      // FreeColors

      unsigned long pixels2[2] = { screen.pixel, screen2.pixel };
      XFreeColors(dpy, colormap, pixels2, 2, 0);

      // StoreColors

      success = XAllocColorCells(dpy, colormap, False, NIL, 0, pixels2, 2);

      // On many contemporary (that is, year 2000) video cards, you can't allocate read / write cells
      // I want my requests to be sent, however.
      if (!success) {
	    XSetErrorHandler(errorHandler);
      }

      XColor colors[2];
      colors[0] = screen;  colors[0].pixel = pixels2[0];
      colors[1] = screen2; colors[1].pixel = pixels2[1];
      XStoreColors(dpy, colormap, colors, 2);

      // StoreNamedColor

      XStoreNamedColor(dpy, colormap, "Wheat", colors[0].pixel, DoBlue);

      XSync(dpy, False);
      XSetErrorHandler(NIL); // Restore the default handler

      // QueryColors

      screen2.pixel = WhitePixelOfScreen(scr);
      XQueryColor(dpy, colormap, &screen2);

      // LookupColor

      success = XLookupColor(dpy, colormap, "DarkCyan", &exact, &screen);

      // CreateCursor

      Cursor cursor = XCreatePixmapCursor(dpy, pixmap, None, &exact, colors, 10, 10);

      // CreateGlyphCursor
      
      Cursor cursor2 = XCreateGlyphCursor(dpy, fs -> fid, fs -> fid, 'X', 0, &exact, colors);

      // FreeCursor
      
      XFreeCursor(dpy, cursor2);

      // RecolorCursor

      XRecolorCursor(dpy, cursor, colors, &exact);

      // QueryBestSize

      success = XQueryBestSize(dpy, CursorShape, RootWindowOfScreen(scr), 100, 20, &width, &height);

      // QueryExtension

      int major_opcode, first_event, first_error;
      XQueryExtension(dpy, "toto", &major_opcode, &first_event, &first_error);

      // ListExtensions

      int nextensions;
      char **extensionList = XListExtensions(dpy, &nextensions);
      for(char **p = extensionList; nextensions; nextensions--, p++) std::cout << *p << std::endl;
      XFree(extensionList);

      // ChangeKeyboardMapping
      // GetKeyboardMapping

      int min_keycodes, max_keycodes;
      XDisplayKeycodes(dpy, &min_keycodes, &max_keycodes);

      int keysyms_per_keycode;
      KeySym *keysyms = XGetKeyboardMapping(dpy, min_keycodes, max_keycodes - min_keycodes + 1,
					    &keysyms_per_keycode);
      XChangeKeyboardMapping(dpy, min_keycodes, keysyms_per_keycode, keysyms, 
			     max_keycodes - min_keycodes + 1);

      // ChangeKeyboardControl
      // GetKeyboardControl

      XKeyboardState keyboardState;
      XGetKeyboardControl(dpy, &keyboardState);

      XKeyboardControl keyboardValues;
      keyboardValues.key_click_percent = keyboardState.key_click_percent;
      keyboardValues.bell_percent = keyboardState.bell_percent;
      keyboardValues.bell_pitch = keyboardState.bell_pitch;
      keyboardValues.bell_duration = keyboardState.bell_duration;
      keyboardValues.led = 1;
      keyboardValues.led_mode = LedModeOn;
      keyboardValues.key = min_keycodes;
      keyboardValues.auto_repeat_mode = AutoRepeatModeDefault;
      XChangeKeyboardControl(dpy, 
			       KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration
			     | KBLed | KBLedMode | KBKey | KBAutoRepeatMode,
			     &keyboardValues);

      // Bell

      XBell(dpy, 90);

      // ChangePointerControl
      // GetPointerControl

      int accel_numerator, accel_denominator, threshold;
      XGetPointerControl(dpy, &accel_numerator, &accel_denominator, &threshold);

      XChangePointerControl(dpy, True, True, accel_numerator, accel_denominator, threshold);

      // SetScreenSaver
      // GetScreenSaver

      int timeout, interval, prefer_blanking, allow_exposures;
      XGetScreenSaver(dpy, &timeout, &interval, &prefer_blanking, &allow_exposures);
      XSetScreenSaver(dpy, timeout, interval, prefer_blanking, allow_exposures);

      // ChangeHosts
      // ListHosts

      int nhosts;
      Bool state;
      XHostAddress *hostList = XListHosts(dpy, &nhosts, &state);

      XHostAddress host;
      host.family = FamilyInternet;
      host.length = 4;
      host.address = "\001\002\003\004";
      XAddHost(dpy, &host);

      // SetAccessControl

      XSetAccessControl(dpy, EnableAccess);

      // SetCloseDownMode

      XSetCloseDownMode(dpy, RetainTemporary);

      // KillClient

      XKillClient(dpy, AllTemporary);

      // RotateProperties

      Atom properties[] = { XInternAtom(dpy, "CUT_BUFFER0", False), 
			    XInternAtom(dpy, "CUT_BUFFER1", False),
			    XInternAtom(dpy, "CUT_BUFFER2", False) };
      XRotateWindowProperties(dpy, RootWindowOfScreen(scr), properties, SIZEOF(properties), -1);

      // ForceScreenSaver

      XForceScreenSaver(dpy, ScreenSaverReset);

      // SetPointerMapping
      // GetPointerMapping

      unsigned char map[64];
      int map_length = XGetPointerMapping(dpy, map, 64);
      XSetPointerMapping(dpy, map, map_length);

      // SetModifierMapping
      // GetModifierMapping

      XModifierKeymap *modmap = XGetModifierMapping(dpy);
      XSetModifierMapping(dpy, modmap);

      // NoOperation

      XNoOp(dpy);

      for(;;) {
	    XEvent e;
	    XNextEvent(dpy, &e);
	    std::cout << "Got an event of type " << e.type << std::endl;
      }
}
Пример #11
0
/**
 * Just like glXUseXFont() but with a rotation parameter.
 * \param rotation may be 0, 90, 180 or 270 only.
 */
void
glXUseRotatedXFontMESA(Font font, int first, int count, int listbase,
                       int rotation)
{
   Display *dpy;
   Window win;
   Pixmap pixmap;
   GC gc;
   XFontStruct *fs;
   GLint swapbytes, lsbfirst, rowlength;
   GLint skiprows, skippixels, alignment;
   unsigned int maxCharWidth, maxCharHeight;
   GLubyte *bm;
   int i;

   if (rotation != 0 &&
       rotation != 90 &&
       rotation != 180 &&
       rotation != 270)
      return;

   dpy = glXGetCurrentDisplay();
   if (!dpy)
      return;			/* I guess glXMakeCurrent wasn't called */
   win = RootWindow(dpy, DefaultScreen(dpy));

   fs = XQueryFont(dpy, font);
   if (!fs) {
      fprintf(stderr, "XQueryFont failed");
      return;
   }

   /* Allocate a GL bitmap that can fit any character */
   maxCharWidth = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
   maxCharHeight = fs->max_bounds.ascent + fs->max_bounds.descent;
   /* use max, in case we're rotating */
   if (rotation == 90 || rotation == 270) {
      /* swap width/height */
      bm = (GLubyte *) malloc((maxCharHeight + 7) / 8 * maxCharWidth);
   }
   else {
      /* normal or upside down */
      bm = (GLubyte *) malloc((maxCharWidth + 7) / 8 * maxCharHeight);
   }
   if (!bm) {
      XFreeFontInfo(NULL, fs, 1);
      fprintf(stderr, "Out of memory in glXUseRotatedXFontMESA");
      return;
   }

   /* Save the current packing mode for bitmaps.  */
   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);

   /* Enforce a standard packing mode which is compatible with
      fill_bitmap() from above.  This is actually the default mode,
      except for the (non)alignment.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   /* Create pixmap and GC */
   pixmap = XCreatePixmap(dpy, win, maxCharWidth, maxCharHeight, 1);
   {
      XGCValues values;
      unsigned long valuemask;
      values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
      values.background = WhitePixel(dpy, DefaultScreen(dpy));
      values.font = fs->fid;
      valuemask = GCForeground | GCBackground | GCFont;
      gc = XCreateGC(dpy, pixmap, valuemask, &values);
   }

   for (i = 0; i < count; i++) {
      const unsigned int c = first + i;
      const int list = listbase + i;
      unsigned int charWidth, charHeight;
      unsigned int bitmapWidth, bitmapHeight;
      GLfloat xOrig, yOrig, xStep, yStep, dtemp;
      const XCharStruct *ch;
      int xPos, yPos;
      int valid;

      /* check on index validity and get the bounds */
      ch = isvalid(fs, c);
      if (!ch) {
	 ch = &fs->max_bounds;
	 valid = 0;
      }
      else {
	 valid = 1;
      }

      /* glBitmap()' parameters:
         straight from the glXUseXFont(3) manpage.  */
      charWidth = ch->rbearing - ch->lbearing;
      charHeight = ch->ascent + ch->descent;
      xOrig = -ch->lbearing;
      yOrig = ch->descent;
      xStep = ch->width;
      yStep = 0;

      /* X11's starting point.  */
      xPos = -ch->lbearing;
      yPos = ch->ascent;

      /* Apply rotation */
      switch (rotation) {
      case 0:
         /* nothing */
         bitmapWidth = charWidth;
         bitmapHeight = charHeight;
         break;
      case 90:
         /* xStep, yStep */
         dtemp = xStep;
         xStep = -yStep;
         yStep = dtemp;
         /* xOrig, yOrig */
         yOrig = xOrig;
         xOrig = charHeight - (charHeight - yPos);
         /* width, height */
         bitmapWidth = charHeight;
         bitmapHeight = charWidth;
         break;
      case 180:
         /* xStep, yStep */
         xStep = -xStep;
         yStep = -yStep;
         /* xOrig, yOrig */
         xOrig = charWidth - xOrig - 1;
         yOrig = charHeight - yOrig - 1;
         bitmapWidth = charWidth;
         bitmapHeight = charHeight;
         break;
      case 270:
         /* xStep, yStep */
         dtemp = xStep;
         xStep = yStep;
         yStep = -dtemp;
         /* xOrig, yOrig */
         dtemp = yOrig;
         yOrig = charWidth - xOrig;
         xOrig = dtemp;
         /* width, height */
         bitmapWidth = charHeight;
         bitmapHeight = charWidth;
         break;
      default:
         /* should never get here */
         ;
      }

      glNewList(list, GL_COMPILE);
      if (valid && bitmapWidth > 0 && bitmapHeight > 0) {

	 fill_bitmap(dpy, pixmap, gc, bitmapWidth, bitmapHeight,
                     charWidth, charHeight,
                     xPos, yPos, c, bm, rotation);

	 glBitmap(bitmapWidth, bitmapHeight, xOrig, yOrig, xStep, yStep, bm);
      }
      else {
	 glBitmap(0, 0, 0.0, 0.0, xStep, yStep, NULL);
      }
      glEndList();
   }

   free(bm);
   XFreeFontInfo(NULL, fs, 1);
   XFreePixmap(dpy, pixmap);
   XFreeGC(dpy, gc);

   /* Restore saved packing modes.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
}
Пример #12
0
static void FreeFontList()
{  int i;
	for( i= 0; i< LastFontList; i++ ){
		XFreeFontInfo( FontList[i].name_list, FontList[i].font_list, FontList[i].font_count );
	}
}
Пример #13
0
/*
 * General text formatting routine which does wrap around
 * if necessary at whitespaces.  The function returns the
 * vertical position it ended at.
 */
int DrawShadowText(Display *display, Window w, GC gc,
		   int x_border, int y_start, const char *str,
		   unsigned long fg, unsigned long bg)
{
    XFontStruct		*font = XQueryFont(display, XGContextFromGC(gc));
    int			y, x, tmp;
    int                 count = 1;
    XWindowAttributes	wattr;

    if (str == NULL || *str == '\0')
	return 0;

    /* Get width of window */
    XGetWindowAttributes(display, w, &wattr);

    /* Start position */
    x = x_border;
    y = y_start + font->ascent;

    do {
	char word[LINE_MAX];
	int wordLen, i;

	for (i = 0; *str && !isspace(*str) && i < LINE_MAX-1; str++, i++)
	    word[i] = *str;
	word[i] = '\0';

	/* Word length in pixels */
	wordLen = XTextWidth(font, word, i);

	/* We need a linebreak? */
	if (x + wordLen > wattr.width - BORDER) {
	    x = x_border;
	    y += font->ascent + font->descent + 1;
	}

	/* Draw word and move cursor to point to after this word */
	ShadowDrawString(display, w, gc, x, y, word, fg, bg);
	x += wordLen;

	/* Handle whitespace */
	for (; isspace(*str); str++)
	    switch (*str) {
		/* New paragraph */
	    case '\n':
		x = x_border;
		y += font->ascent + font->descent + 1;
		break;

		/* Just a space */
	    default:
		x += XTextWidth(font, " ", 1);
		break;
	    }
    } while (*str != '\0');

    tmp = font->descent+1;

    XFreeFontInfo(NULL, font, count);

    return y + tmp;
}
Пример #14
0
static void Redisplay (XtcwpAxesWidget w, XEvent *event, Region region)
{
    Display *dpy=XtDisplay(w);
    Window win=XtWindow(w);
    int x=w->axes.x;
    int y=w->axes.y;
    int width=w->axes.width;
    int height=w->axes.height;
    float x1beg=w->axes.x1beg;
    float x1end=w->axes.x1end;
    float x2beg=w->axes.x2beg;
    float x2end=w->axes.x2end;
    float p1beg=w->axes.p1beg;
    float p1end=w->axes.p1end;
    float p2beg=w->axes.p2beg;
    float p2end=w->axes.p2end;
    int n1tic=w->axes.n1tic;
    int n2tic=w->axes.n2tic;
    int grid1=w->axes.grid1;
    int grid2=w->axes.grid2;
    char *label1=w->axes.label1;
    char *label2=w->axes.label2;
    char *title=w->axes.title;
    Font labelfont=w->axes.labelfont;
    Font titlefont=w->axes.titlefont;
    Pixel axescolor=w->axes.axescolor;
    Pixel gridcolor=w->axes.gridcolor;
    Pixel titlecolor=w->axes.titlecolor;
    int style=w->axes.style;
    XGCValues values;
    GC gca,gcg,gct;
    XtcwpAxesCallbackStruct cb;
    XFontStruct *fa,*ft;
    XCharStruct cs;
    int labelca,labelcd,labelch,labelcw,titleca,titlech,
        ntic,xa,ya,tw,ticsize,ticb,numb,labelb,grided,grid,
        n1num,n2num,dummy;
    size_t lstr;
    float dnum,fnum,dtic,amin,amax,base,scale,anum,atic,azero;
    float d1num=0.0,f1num=0.0,d2num=0.0,f2num=0.0;
    char str[256],dash[2],*label;

    /* if not visible, then simply return */
    if (!w->core.visible) return;

    /* call callbacks before drawing axes (so grid will be on top) */
    fillCallbackStruct(w,XtcwpCR_EXPOSE,event,region,&cb);
    XtCallCallbacks ((Widget) w,XtNexposeCallback,&cb);

    /* create GCs */
    gca = XCreateGC(dpy,win,0,&values);
    gcg = XCreateGC(dpy,win,0,&values);
    gct = XCreateGC(dpy,win,0,&values);

    /* set colors */
    XSetForeground(dpy,gca,axescolor);
    XSetForeground(dpy,gcg,gridcolor);
    XSetForeground(dpy,gct,titlecolor);

    /* set fonts and determine character dimensions */
    XSetFont(dpy,gca,labelfont);
    XSetFont(dpy,gct,titlefont);
    fa = XQueryFont(dpy,labelfont);
    XTextExtents(fa,"2",1,&dummy,&dummy,&dummy,&cs);
    labelca = cs.ascent;
    labelcd = cs.descent;
    labelch = labelca+labelcd;
    labelcw = cs.width;
    ft = XQueryFont(dpy,titlefont);
    titleca = ft->max_bounds.ascent;
    titlech = ft->max_bounds.ascent+ft->max_bounds.descent;

    /* determine tic size */
    ticsize = labelcw;

    /* determine numbered tic intervals */
    n1num = (style==XtcwpNORMAL ? width : height)/(8*labelcw);
    scaxis(x1beg,x1end,&n1num,&d1num,&f1num);
    n2num = (style==XtcwpNORMAL ? height : width)/(8*labelcw);
    scaxis(x2beg,x2end,&n2num,&d2num,&f2num);

    /* draw horizontal axis */
    if (style==XtcwpNORMAL) {
        amin = (x1beg<x1end)?x1beg:x1end;
        amax = (x1beg>x1end)?x1beg:x1end;
        dnum = d1num;
        fnum = f1num;
        ntic = n1tic;
        scale = width/(x1end+p1end-x1beg-p1beg);
        base = x-scale*(x1beg+p1beg);
        ya = y+height;
        ticb = ticsize;
        numb = ticb+labelca+ticsize/4;
        labelb = numb+labelch+ticsize/4;
        grid = grid1;
        label = label1;
    } else {
        amin = (x2beg<x2end)?x2beg:x2end;
        amax = (x2beg>x2end)?x2beg:x2end;
        dnum = d2num;
        fnum = f2num;
        ntic = n2tic;
        scale = width/(x2end+p2end-x2beg-p2beg);
        base = x-scale*(x2beg+p2beg);
        ya = y;
        ticb = -ticsize;
        numb = ticb-labelcd-ticsize/4;
        labelb = numb-labelch-ticsize/4;
        grid = grid2;
        label = label2;
    }
    if (grid==XtcwpSOLID) {
        XSetLineAttributes(dpy,gcg,1L,LineSolid,CapButt,JoinMiter);
        grided = True;
    } else if (grid==XtcwpDASH) {
        grided = True;
        XSetLineAttributes(dpy,gcg,1L,LineOnOffDash,CapButt,JoinMiter);
        dash[0] = 8;
        dash[1] = 4;
        XSetDashes(dpy,gcg,0,dash,2);
    } else if (grid==XtcwpDOT) {
        grided = True;
        XSetLineAttributes(dpy,gcg,1L,LineOnOffDash,CapButt,JoinMiter);
        dash[0] = 1;
        dash[1] = 4;
        XSetDashes(dpy,gcg,0,dash,2);
    } else
        grided = False;
    azero = 0.0001*(amax-amin);
    for (anum=fnum; anum<=amax; anum+=dnum) {
        if (anum<amin) continue;
        xa = base+scale*anum;
        if (grided) XDrawLine(dpy,win,gcg,xa,y,xa,y+height);
        XDrawLine(dpy,win,gca,xa,ya,xa,ya+ticb);
        if (anum>-azero && anum<azero)
            sprintf(str,"%1.5g",0.0);
        else
            sprintf(str,"%1.5g",anum);
        lstr = strlen(str);
        tw = XTextWidth(fa,str,(int)lstr);
        XDrawString(dpy,win,gca,xa-tw/2,ya+numb,str,(int)lstr);
    }
    dtic = dnum/ntic;
    for (atic=fnum-ntic*dtic-dtic; atic<=amax; atic+=dtic) {
        if (atic<amin) continue;
        xa = base+scale*atic;
        XDrawLine(dpy,win,gca,xa,ya,xa,ya+ticb/2);
    }
    lstr = strlen(label);
    tw = XTextWidth(fa,label,(int)lstr);
    XDrawString(dpy,win,gca,x+width/2-tw/2,ya+labelb,label,(int)lstr);

    /* draw vertical axis */
    if (style==XtcwpNORMAL) {
        amin = (x2beg<x2end)?x2beg:x2end;
        amax = (x2beg>x2end)?x2beg:x2end;
        dnum = d2num;
        fnum = f2num;
        ntic = n2tic;
        scale = -height/(x2end+p2end-x2beg-p2beg);
        base = y+height-scale*(x2beg+p2beg);
        grid = grid2;
        label = label2;
    } else {
        amin = (x1beg<x1end)?x1beg:x1end;
        amax = (x1beg>x1end)?x1beg:x1end;
        dnum = d1num;
        fnum = f1num;
        ntic = n1tic;
        scale = height/(x1end+p1end-x1beg-p1beg);
        base = y-scale*(x1beg+p1beg);
        grid = grid1;
        label = label1;
    }
    xa = x;
    ticb = -ticsize;
    numb = ticb-ticsize/4;
    if (grid==XtcwpSOLID) {
        XSetLineAttributes(dpy,gcg,1L,LineSolid,CapButt,JoinMiter);
        grided = True;
    } else if (grid==XtcwpDASH) {
        grided = True;
        XSetLineAttributes(dpy,gcg,1L,LineOnOffDash,CapButt,JoinMiter);
        dash[0] = 8;
        dash[1] = 4;
        XSetDashes(dpy,gcg,0,dash,2);
    } else if (grid==XtcwpDOT) {
        grided = True;
        XSetLineAttributes(dpy,gcg,1L,LineOnOffDash,CapButt,JoinMiter);
        dash[0] = 1;
        dash[1] = 4;
        XSetDashes(dpy,gcg,0,dash,2);
    } else
        grided = False;
    azero = 0.0001*(amax-amin);
    for (anum=fnum; anum<=amax; anum+=dnum) {
        if (anum<amin) continue;
        ya = base+scale*anum;
        if (grided) XDrawLine(dpy,win,gcg,x,ya,x+width,ya);
        XDrawLine(dpy,win,gca,xa,ya,xa+ticb,ya);
        if (anum>-azero && anum<azero)
            sprintf(str,"%1.5g",0.0);
        else
            sprintf(str,"%1.5g",anum);
        lstr = strlen(str);
        tw = XTextWidth(fa,str,(int)lstr);
        XDrawString(dpy,win,gca,xa+numb-tw,ya+labelca/4,str,(int)lstr);
    }
    dtic = dnum/ntic;
    for (atic=fnum-ntic*dtic-dtic; atic<=amax; atic+=dtic) {
        if (atic<amin) continue;
        ya = base+scale*atic;
        XDrawLine(dpy,win,gca,xa,ya,xa+ticb/2,ya);
    }
    lstr = strlen(label);
    tw = XTextWidth(fa,label,(int)lstr);
    xa = x+ticb-5*labelcw-ticsize/2;
    if (xa<labelch+1) xa = labelch+1;
    XtcwpDrawString90(dpy,win,gca,xa,y+height/2+tw/2,label,(int)lstr);

    /* draw title */
    lstr = strlen(title);
    tw = XTextWidth(ft,title,(int)lstr);
    if (style==XtcwpNORMAL) {
        XClearArea(dpy,win,0,y+labelca/4-labelch-labelch-titleca,
                   w->core.width,titlech,False);
        XDrawString(dpy,win,gct,
                    x+width/2-tw/2,
                    y+labelca/4-labelch-labelch,title,(int)lstr);
    } else {
        XClearArea(dpy,win,0,y+height+labelca/4+labelch,
                   w->core.width,titlech,False);
        XDrawString(dpy,win,gct,
                    x+width/2-tw/2,
                    y+height+labelca/4+labelch+titleca,title,(int)lstr);
    }

    /* draw axes box */
    XDrawRectangle(dpy,win,gca,x,y,width,height);

    /* free GCs and font info */
    XFreeGC(dpy,gca);
    XFreeGC(dpy,gcg);
    XFreeGC(dpy,gct);
    XFreeFontInfo(NULL,fa,1);
    XFreeFontInfo(NULL,ft,1);
}
Пример #15
0
/* Finds the set of scalable fonts on the system; picks one;
   and loads that font in a random pixel size.
   Returns False if something went wrong.
 */
static Bool
pick_font_1 (state *s, sentence *se)
{
  Bool ok = False;
  char pattern[1024];

# ifndef HAVE_COCOA /* real Xlib */
  char **names = 0;
  char **names2 = 0;
  XFontStruct *info = 0;
  int count = 0, count2 = 0;
  int i;

  if (se->font)
    {
      XFreeFont (s->dpy, se->font);
      free (se->font_name);
      se->font = 0;
      se->font_name = 0;
    }

  if (s->font_override)
    sprintf (pattern, "%.200s", s->font_override);
  else
    sprintf (pattern, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
             "*",         /* foundry */
             "*",         /* family */
             "*",         /* weight */
             "*",         /* slant */
             "*",         /* swidth */
             "*",         /* adstyle */
             "0",         /* pixel size */
             "0",         /* point size */
             "0",         /* resolution x */
             "0",         /* resolution y */
             "p",         /* spacing */
             "0",         /* avg width */
             s->charset); /* registry + encoding */

  names = XListFonts (s->dpy, pattern, 1000, &count);

  if (count <= 0)
    {
      if (s->font_override)
        fprintf (stderr, "%s: -font option bogus: %s\n", progname, pattern);
      else
        fprintf (stderr, "%s: no scalable fonts found!  (pattern: %s)\n",
                 progname, pattern);
      exit (1);
    }

  i = random() % count;

  names2 = XListFontsWithInfo (s->dpy, names[i], 1000, &count2, &info);
  if (count2 <= 0)
    {
      fprintf (stderr, "%s: pattern %s\n"
                "     gave unusable %s\n\n",
               progname, pattern, names[i]);
      goto FAIL;
    }

  {
    XFontStruct *font = &info[0];
    unsigned long value = 0;
    char *foundry=0, *family=0, *weight=0, *slant=0, *setwidth=0, *add_style=0;
    unsigned long pixel=0, point=0, res_x=0, res_y=0;
    char *spacing=0;
    unsigned long avg_width=0;
    char *registry=0, *encoding=0;
    Atom a;
    char *bogus = "\"?\"";

# define STR(ATOM,VAR)					\
  bogus = (ATOM);					\
  a = XInternAtom (s->dpy, (ATOM), False);		\
  if (XGetFontProperty (font, a, &value))		\
    VAR = XGetAtomName (s->dpy, value);			\
  else							\
    goto FAIL2

# define INT(ATOM,VAR)					\
  bogus = (ATOM);					\
  a = XInternAtom (s->dpy, (ATOM), False);		\
  if (!XGetFontProperty (font, a, &VAR) ||		\
      VAR > 9999)					\
    goto FAIL2

    STR ("FOUNDRY",          foundry);
    STR ("FAMILY_NAME",      family);
    STR ("WEIGHT_NAME",      weight);
    STR ("SLANT",            slant);
    STR ("SETWIDTH_NAME",    setwidth);
    STR ("ADD_STYLE_NAME",   add_style);
    INT ("PIXEL_SIZE",       pixel);
    INT ("POINT_SIZE",       point);
    INT ("RESOLUTION_X",     res_x);
    INT ("RESOLUTION_Y",     res_y);
    STR ("SPACING",          spacing);
    INT ("AVERAGE_WIDTH",    avg_width);
    STR ("CHARSET_REGISTRY", registry);
    STR ("CHARSET_ENCODING", encoding);

#undef INT
#undef STR

    pixel = pick_font_size (s);

#if 0
    /* Occasionally change the aspect ratio of the font, by increasing
       either the X or Y resolution (while leaving the other alone.)

       #### Looks like this trick doesn't really work that well: the
            metrics of the individual characters are ok, but the
            overall font ascent comes out wrong (unscaled.)
     */
    if (! (random() % 8))
      {
        double n = 2.5 / 3;
        double scale = 1 + (frand(n) + frand(n) + frand(n));
        if (random() % 2)
          res_x *= scale;
        else
          res_y *= scale;
      }
# endif

    sprintf (pattern,
             "-%s-%s-%s-%s-%s-%s-%ld-%s-%ld-%ld-%s-%s-%s-%s",
             foundry, family, weight, slant, setwidth, add_style,
             pixel, "*", /* point, */
             res_x, res_y, spacing,
             "*", /* avg_width */
             registry, encoding);
    ok = True;

  FAIL2:
    if (!ok)
      fprintf (stderr, "%s: font has bogus %s property: %s\n",
               progname, bogus, names[i]);

    if (foundry)   XFree (foundry);
    if (family)    XFree (family);
    if (weight)    XFree (weight);
    if (slant)     XFree (slant);
    if (setwidth)  XFree (setwidth);
    if (add_style) XFree (add_style);
    if (spacing)   XFree (spacing);
    if (registry)  XFree (registry);
    if (encoding)  XFree (encoding);
  }

 FAIL: 

  XFreeFontInfo (names2, info, count2);
  XFreeFontNames (names);

# else  /* HAVE_COCOA */

  if (s->font_override)
    sprintf (pattern, "%.200s", s->font_override);
  else
    {
      const char *family = "random";
      const char *weight = ((random() % 2)  ? "normal" : "bold");
      const char *slant  = ((random() % 2)  ? "o" : "r");
      int size = 10 * pick_font_size (s);
      sprintf (pattern, "*-%s-%s-%s-*-%d-*", family, weight, slant, size);
    }
  ok = True;
# endif /* HAVE_COCOA */

  if (! ok) return False;

  se->font = XLoadQueryFont (s->dpy, pattern);
  if (! se->font)
    {
      if (s->debug_p)
        fprintf (stderr, "%s: unable to load font %s\n",
                 progname, pattern);
      return False;
    }

  if (se->font->min_bounds.width == se->font->max_bounds.width &&
      !s->font_override)
    {
      /* This is to weed out
         "-urw-nimbus mono l-medium-o-normal--*-*-*-*-p-*-iso8859-1" and
         "-urw-courier-medium-r-normal--*-*-*-*-p-*-iso8859-1".
         We asked for only proportional fonts, but this fixed-width font
         shows up anyway -- but it has goofy metrics (see below) so it
         looks terrible anyway.
       */
      if (s->debug_p)
        fprintf (stderr,
                 "%s: skipping bogus monospace non-charcell font: %s\n",
                 progname, pattern);
      return False;
    }

  if (s->debug_p) 
    fprintf(stderr, "%s: %s\n", progname, pattern);

  se->font_name = strdup (pattern);
  XSetFont (s->dpy, se->fg_gc, se->font->fid);
  return True;
}
Пример #16
0
void
Fake_glXUseXFont(Font font, int first, int count, int listbase)
{
   Display *dpy;
   Window win;
   Pixmap pixmap;
   GC gc;
   XGCValues values;
   unsigned long valuemask;
   XFontStruct *fs;
   GLint swapbytes, lsbfirst, rowlength;
   GLint skiprows, skippixels, alignment;
   unsigned int max_width, max_height, max_bm_width, max_bm_height;
   GLubyte *bm;
   int i;

   dpy = glXGetCurrentDisplay();
   if (!dpy)
      return;			/* I guess glXMakeCurrent wasn't called */
   win = RootWindow(dpy, DefaultScreen(dpy));

   fs = XQueryFont(dpy, font);
   if (!fs) {
      _mesa_error(NULL, GL_INVALID_VALUE,
		  "Couldn't get font structure information");
      return;
   }

   /* Allocate a bitmap that can fit all characters.  */
   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
   max_bm_width = (max_width + 7) / 8;
   max_bm_height = max_height;

   bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte));
   if (!bm) {
      XFreeFontInfo(NULL, fs, 1);
      _mesa_error(NULL, GL_OUT_OF_MEMORY,
		  "Couldn't allocate bitmap in glXUseXFont()");
      return;
   }

#if 0
   /* get the page info */
   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
   firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
   lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
   rows = fs->max_byte1 - fs->min_byte1 + 1;
   unsigned int first_char, last_char, pages, rows;
#endif

   /* Save the current packing mode for bitmaps.  */
   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);

   /* Enforce a standard packing mode which is compatible with
      fill_bitmap() from above.  This is actually the default mode,
      except for the (non)alignment.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
   values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
   values.background = WhitePixel(dpy, DefaultScreen(dpy));
   values.font = fs->fid;
   valuemask = GCForeground | GCBackground | GCFont;
   gc = XCreateGC(dpy, pixmap, valuemask, &values);
   XFreePixmap(dpy, pixmap);

#ifdef DEBUG
   if (debug_xfonts)
      dump_font_struct(fs);
#endif

   for (i = 0; i < count; i++) {
      unsigned int width, height, bm_width, bm_height;
      GLfloat x0, y0, dx, dy;
      XCharStruct *ch;
      int x, y;
      unsigned int c = first + i;
      int list = listbase + i;
      int valid;

      /* check on index validity and get the bounds */
      ch = isvalid(fs, c);
      if (!ch) {
	 ch = &fs->max_bounds;
	 valid = 0;
      }
      else {
	 valid = 1;
      }

#ifdef DEBUG
      if (debug_xfonts) {
	 char s[7];
	 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
	 dump_char_struct(ch, s);
      }
#endif

      /* glBitmap()' parameters:
         straight from the glXUseXFont(3) manpage.  */
      width = ch->rbearing - ch->lbearing;
      height = ch->ascent + ch->descent;
      x0 = -ch->lbearing;
      y0 = ch->descent - 0;	/* XXX used to subtract 1 here */
      /* but that caused a conformace failure */
      dx = ch->width;
      dy = 0;

      /* X11's starting point.  */
      x = -ch->lbearing;
      y = ch->ascent;

      /* Round the width to a multiple of eight.  We will use this also
         for the pixmap for capturing the X11 font.  This is slightly
         inefficient, but it makes the OpenGL part real easy.  */
      bm_width = (width + 7) / 8;
      bm_height = height;

      glNewList(list, GL_COMPILE);
      if (valid && (bm_width > 0) && (bm_height > 0)) {

	 memset(bm, '\0', bm_width * bm_height);
	 fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);

	 glBitmap(width, height, x0, y0, dx, dy, bm);
#ifdef DEBUG
	 if (debug_xfonts) {
	    printf("width/height = %u/%u\n", width, height);
	    printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
	    dump_bitmap(bm_width, bm_height, bm);
	 }
#endif
      }
      else {
	 glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
      }
      glEndList();
   }

   free(bm);
   XFreeFontInfo(NULL, fs, 1);
   XFreeGC(dpy, gc);

   /* Restore saved packing modes.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
}
Пример #17
0
int main(int argc, char *argv[])
{
   /* default values for -f, -i, -r, -c, -b, -g */
   char *fontname = "*";
   char *filename = "font.pcx";
   int start_char = 32, end_char = 255;
   int ccolor = 000000000;
   int bcolor = 255255255;
   int gcolor = 255000255;
   /* X11 variables */
   Display *display;
   int screen_number;
   int default_depth;
   Window window;
   Font font;
   GC gc, gc2;
   Pixmap pixmap;
   XImage *image;
   XCharStruct overall;
   /* misc variables */
   int bitmap_width, bitmap_height;
   int max_ascent, max_descent;
   int max_width, max_height;
   int i, opt, x, y, cx, cy, sx, sy, lines;
   unsigned long black, white;
   BITMAP *bitmap;
   RGB palette[256];

   /* show usage if no options  */
   if (argc == 1) {
      usage(argv[0]);
      exit(EXIT_SUCCESS);
   }

   /* only to access bitmap operations */
   install_allegro(SYSTEM_NONE, &errno, atexit);

   /* parse options  */
   opterr = 0;
   while ((opt = getopt(argc, argv, "f:o:z:c:b:g:r:h")) != EOF) {
      switch (opt) {
	 case 'f':
	    fontname = optarg;
	    break;
	 case 'o':
	    filename = optarg;
	    break;
	 case 'c':
	    ccolor = atol(optarg);
	    break;
	 case 'b':
	    bcolor = atol(optarg);
	    break;
	 case 'g':
	    gcolor = atol(optarg);
	    break;
	 case 'r':
	    {
	       char *str;
	       start_char = strtol(optarg, &str, 0);
	       end_char = strtol(str + 1, NULL, 0);
	       break;
	    }
	 case 'h':
	    usage(argv[0]);
	    exit(EXIT_SUCCESS);
	 default:
	    fprintf(stderr, "%s: unrecognized option -- '%c'\n", argv[0],
		    optopt);
	    fprintf(stderr, "%s: try '%s -h' for more information\n",
		    argv[0], argv[0]);
	    exit(EXIT_FAILURE);
      }
   }

   /* open display */
   display = XOpenDisplay(0);
   if (display == 0) {
      fprintf(stderr, "%s: XOpenDisplay failed\n", argv[0]);
      exit(EXIT_FAILURE);
   }

   /* default screen number and window */
   screen_number = XDefaultScreen(display);
   default_depth = XDefaultDepth(display, screen_number);
   window = XDefaultRootWindow(display);

   /* load font */
   font = XLoadFont(display, fontname);

   /* create gcs */
   {
      unsigned long val_mask;
      XGCValues val_bits;
      val_mask = GCForeground | GCBackground | GCFont | GCFunction;
      val_bits.function = GXcopy;
      val_bits.foreground = white = WhitePixel(display, screen_number);
      val_bits.background = black = BlackPixel(display, screen_number);
      val_bits.font = font;
      gc = XCreateGC(display, window, val_mask, &val_bits);
      val_mask = GCForeground;
      val_bits.foreground = black;
      gc2 = XCreateGC(display, window, val_mask, &val_bits);
   }

   /* query font ascent and descent */
   {
      XFontStruct *xfs;
      int min, max;
      xfs = XQueryFont(display, font);
      max_ascent = xfs->ascent;
      max_descent = xfs->descent;

      if (xfs->min_byte1 == 0 && xfs->max_byte1 == 0) {
	 min = xfs->min_char_or_byte2;
	 max = xfs->max_char_or_byte2;
      }
      else {
	 min = (xfs->min_byte1 << 8) + xfs->min_char_or_byte2;
	 max = (xfs->max_byte1 << 8) + xfs->max_char_or_byte2;
      }

      if (start_char < min || end_char > max)
	 fprintf(stderr,
		 "You specified characters %04x-%04x, but this font "
		 "only has the range %04x-%04x\n", start_char, end_char,
		 min, max);

      XFreeFontInfo(NULL, xfs, 0);
   }

   /* calculate bitmap width and maximum ascent and descent of characters
    * (can exceed the font ascent/descent queried above!) */
   max_width = 0;
   lines = 1 + (end_char - start_char) / 16;
   for (cy = 0; cy < lines; cy++) {

      for (cx = 0; cx < 16 && start_char + cy * 16 + cx <= end_char; cx++) {
	 int dir, ascent, descent;
	 int width;
	 XChar2b string[2] = { {0, 0}, {0, 0} };

	 /* query character size */
	 string[0].byte1 = (start_char + cy * 16 + cx) >> 8;
	 string[0].byte2 = (start_char + cy * 16 + cx) & 255;
	 XQueryTextExtents16(display, font, string, 1, &dir, &ascent,
			     &descent, &overall);
	 width = overall.width;
	 if (width < 1)
	    width = 1;

	 if (width > max_width)
	    max_width = width;

	 if (max_ascent < overall.ascent)
	    max_ascent = overall.ascent;
	 if (max_descent < overall.descent)
	    max_descent = overall.descent;
      }

   }

   max_height = max_ascent + max_descent;

   bitmap_width = (max_width + 1) * 16 + 1;
   bitmap_height = (max_height + 1) * lines + 1;

   /* create bitmap */
   bitmap = create_bitmap(bitmap_width, bitmap_height);
   if (bitmap == 0) {
      fprintf(stderr, "%s: can not create bitmap\n", argv[0]);
      exit(EXIT_FAILURE);
   }

   /* fill with filler color */
   clear_to_color(bitmap, 255);

   /* process all characters */
   sy = 1;
   for (cy = 0; cy < lines; cy++) {

      sx = 1;
      for (cx = 0; cx < 16 && start_char + cy * 16 + cx <= end_char; cx++) {
	 int dir, ascent, descent;
	 XChar2b string[2] = { {0, 0}, {0, 0} };

	 /* query character size */
	 string[0].byte1 = (start_char + cy * 16 + cx) >> 8;
	 string[0].byte2 = (start_char + cy * 16 + cx) & 255;
	 XQueryTextExtents16(display, font, string, 1, &dir, &ascent,
			     &descent, &overall);

	 if (overall.width < 1)
	    overall.width = 1;

	 /* create pixmap and draw character there */
	 pixmap =
	     XCreatePixmap(display, window, overall.width, max_height,
			   default_depth);
	 /* some fonts draw outside their ascent/descent, so we need to clear
	  * the pixmap before drawing the glyph */
	 XFillRectangle(display, pixmap, gc2, 0, 0, overall.width,
			max_height);
	 XDrawImageString16(display, pixmap, gc, 0, max_ascent, string, 1);

	 /* create image with pixmap contents */
	 image =
	     XGetImage(display, pixmap, 0, 0, overall.width, max_height,
		       AllPlanes, ZPixmap);
	 if (image == 0) {
	    fprintf(stderr, "%s: can not get image\n", argv[0]);
	    exit(EXIT_FAILURE);
	 }

	 /* copy image to bitmap */
	 for (y = 0; y < max_height; y++)
	    for (x = 0; x < overall.width; x++) {
	       if (XGetPixel(image, x, y) == white)
		  putpixel(bitmap, sx + x, sy + y, 1);
	       else
		  putpixel(bitmap, sx + x, sy + y, 0);
	    }

	 XDestroyImage(image);
	 XFreePixmap(display, pixmap);

	 sx += max_width + 1;
      }
      sy += max_height + 1;
   }

   /* initialize palette */
   for (i = 0; i < 256; i++)
      palette[i].r = palette[i].g = palette[i].b = 0;

#define CLAMP_COL(v) (((v / 4) > 63) ? 63 : (v / 4))
   palette[0].r = CLAMP_COL(bcolor / 1000000);
   palette[0].g = CLAMP_COL((bcolor % 1000000) / 1000);
   palette[0].b = CLAMP_COL(bcolor % 1000);
   palette[1].r = CLAMP_COL(ccolor / 1000000);
   palette[1].g = CLAMP_COL((ccolor % 1000000) / 1000);
   palette[1].b = CLAMP_COL(ccolor % 1000);
   palette[255].r = CLAMP_COL(gcolor / 1000000);
   palette[255].g = CLAMP_COL((gcolor % 1000000) / 1000);
   palette[255].b = CLAMP_COL(gcolor % 1000);
#undef CLAMP_COL
   save_pcx(filename, bitmap, palette);

   /* clean up */
   destroy_bitmap(bitmap);
   XFreeGC(display, gc);
   XFreeGC(display, gc2);
   XUnloadFont(display, font);
   XCloseDisplay(display);

   exit(EXIT_SUCCESS);
}