Esempio n. 1
0
int GrSaveContextToPgm( GrContext *grc, char *pgmfn, char *docn )
{
  FILE *f;
  GrContext grcaux;
  char cab[81];
  unsigned char grey;
  int rgb[3];
  int x, y;

  if( (f = fopen( pgmfn,"wb" )) == NULL ) return -1;
  
  GrSaveContext( &grcaux );
  if( grc != NULL ) GrSetContext( grc );
  sprintf( cab,"P5\n#" );
  fwrite( cab,1,strlen( cab ),f );
  if( docn != NULL ) fwrite( docn,1,strlen( docn ), f );
  sprintf( cab,"\n%d %d\n255\n",GrSizeX(),GrSizeY() );
  fwrite( cab,1,strlen( cab ),f );
  for( y=0; y<GrSizeY(); y++ )
    for( x=0; x<GrSizeX(); x++ ){
      GrQueryColor( GrPixel( x,y ),&rgb[0],&rgb[1],&rgb[2] );
      grey = (0.229 * rgb[0]) + (0.587 * rgb[1]) + (0.114 * rgb[2]);
      fwrite( &grey,1,1,f );
      }
  GrSetContext( &grcaux );
  fclose( f );

  return 0;
}
Esempio n. 2
0
int GrSaveContextToPpm( GrContext *grc, char *ppmfn, char *docn )
{
  FILE *f;
  GrContext grcaux;
  char cab[81];
  unsigned char brgb[3];
  int x, y, r, g, b;

  if( (f = fopen( ppmfn,"wb" )) == NULL ) return -1;
  
  GrSaveContext( &grcaux );
  if( grc != NULL ) GrSetContext( grc );
  sprintf( cab,"P6\n#" );
  fwrite( cab,1,strlen( cab ),f );
  if( docn != NULL ) fwrite( docn,1,strlen( docn ), f );
  sprintf( cab,"\n%d %d\n255\n",GrSizeX(),GrSizeY() );
  fwrite( cab,1,strlen( cab ),f );
  for( y=0; y<GrSizeY(); y++ )
    for( x=0; x<GrSizeX(); x++ ){
      GrQueryColor( GrPixel( x,y ),&r,&g,&b );
      brgb[0] = r;
      brgb[1] = g;
      brgb[2] = b;
      fwrite( brgb,1,3,f );
      }
  GrSetContext( &grcaux );
  fclose( f );

  return 0;
}
Esempio n. 3
0
static void TestFunc(void)
{
  int  x = GrSizeX();
  int  y = GrSizeY();
  int  ww = (x / 2) - 10;
  int  wh = (y / 2) - 10;
  GrColor c;

  GrContext *w1 = GrCreateSubContext(5, 5, ww+4, wh+4, NULL, NULL);
  GrContext *w2 = GrCreateSubContext(15+ww, 5, ww+ww+14, wh+4, NULL, NULL);
  GrContext *w3 = GrCreateSubContext(5, 15+wh, ww+4, wh+wh+14, NULL, NULL);
  GrContext *w4 = GrCreateSubContext(15+ww, 15+wh, ww+ww+14, wh+wh+14, NULL, NULL);

  GrSetContext(w1);
  c = GrAllocColor(200, 100, 100);
  drawing(0, 0, ww, wh, c, GrBlack());
  GrBox(0, 0, ww-1, wh-1, c);

  GrSetContext(w2);
  c = GrAllocColor(100, 200, 200);
  drawing(0, 0, ww, wh, c, GrBlack());
  GrBox(0, 0, ww-1, wh-1, c);

  GrSetContext(w3);
  c = GrAllocColor(200, 200, 0);
  drawing(0, 0, ww, wh, c, GrBlack());
  GrBox(0, 0,ww-1, wh-1, c);

  GrSetContext(w4);
  c = GrAllocColor(0, 100, 200);
  drawing(0, 0, ww, wh, c, GrBlack());
  GrBox(0, 0, ww-1, wh-1, c);

  GrSetContext(NULL);
}
Esempio n. 4
0
/* Copy area (x1,y1)-(x2,y2) from a bitmap (if bm==NULL from the screen)
   and create a structure ws_bitmap with the area in bitmap. Returns NULL if
   not successful, the pointer to the structure otherwise. */
struct ws_bitmap *ws_savebitmap(struct ws_bitmap *bm, int x1, int y1,
                                int xsize,
                                int ysize)
{
    GrContext *gc;
    struct ws_bitmap *bmap;


    if ( xsize < 0 || ysize < 0 || y1 < 0 || x1 < 0 || x1 + xsize > GrSizeX()
       || y1 + ysize > GrSizeY() ) {
        return NULL;
    }

    checkmem( bmap = MALLOC( sizeof(struct ws_bitmap) ) );
    checkmem( gc = GrCreateContext(xsize, ysize, NULL, NULL) );
    GrBitBlt(gc, 0, 0, bm == NULL ? NULL : bm->bitmap, x1, y1, x1 + xsize - 1,
             y1 + ysize - 1,
             GrWRITE);
    bmap->bitmap = (void *)gc;
    bmap->xpos = x1;
    bmap->ypos = y1;
    bmap->xsize = xsize;
    bmap->ysize = ysize;
    bmap->w = NULL;
    return bmap;
}
Esempio n. 5
0
void displayfont(GrFont *font,char *text,int len)
{
	GrTextOption opt;
	int ww,hh;
	int bx,by;
	int bw,bh;
	GrEvent ev;

	memset(&opt,0,sizeof(opt));
	opt.txo_font   = font;
	opt.txo_xalign = GR_ALIGN_LEFT;
	opt.txo_yalign = GR_ALIGN_TOP;
	GrFilledBox(0,0,GrSizeX(),GrSizeY(),GrBlack());
	opt.txo_direct    = GR_TEXT_RIGHT;
	opt.txo_fgcolor.v = GrBlack();
	opt.txo_bgcolor.v = c1;
	ww = GrStringWidth(text,len,&opt);
	hh = GrStringHeight(text,len,&opt);
	bw = ww+2*hh;
	bh = ww;
	bx = cx - bw/2;
	by = cy - bh/2;
	GrDrawString(text,len,bx+hh,by,&opt);
	opt.txo_direct    = GR_TEXT_DOWN;
	opt.txo_bgcolor.v = c2;
	GrDrawString(text,len,bx+bw-hh,by,&opt);
	opt.txo_direct    = GR_TEXT_LEFT;
	opt.txo_bgcolor.v = c3;
	GrDrawString(text,len,bx+bw-ww-hh,by+bh-hh,&opt);
	opt.txo_direct    = GR_TEXT_UP;
	opt.txo_bgcolor.v = c4;
	GrDrawString(text,len,bx,by+bh-ww,&opt);
	GrEventWaitKeyOrClick(&ev);
	GrClearClipBox(GrBlack());
	opt.txo_direct    = GR_TEXT_RIGHT;
	opt.txo_fgcolor.v = c1;
	opt.txo_bgcolor.v = GrBlack();
	bx = GrSizeX() / 16;
	by = GrSizeY() / 16;
	bx = (bx + 7) & ~7;
	while(by < GrSizeY()) {
	    GrDrawString(test_text,strlen(test_text),bx,by,&opt);
	    opt.txo_fgcolor.v ^= GR_UNDERLINE_TEXT;
	    by += hh;
	}
	GrEventWaitKeyOrClick(&ev);
}
Esempio n. 6
0
static void gnewl(void)
{
	cury += GrCharHeight('A', &opt) + deltay;
	curx = 0;
	if(cury + GrCharHeight('A', &opt) > GrSizeY() + deltay) {
//	    if(GrKeyRead() == GrKey_F10) {
//		GrUnloadFont(opt.txo_font);
//		exit(0);
//	    }
	    GrClearScreen(opt.txo_bgcolor.v);
	    cury = 0;
	}
}
Esempio n. 7
0
int GrSaveContextToPbm( GrContext *grc, char *pbmfn, char *docn )
{
  FILE *f;
  GrContext grcaux;
  char cab[81];
  int currentbyte = 0, currentbit = 7;
  int x, y;

  if( (f = fopen( pbmfn,"wb" )) == NULL ) return -1;
  
  GrSaveContext( &grcaux );
  if( grc != NULL ) GrSetContext( grc );
  sprintf( cab,"P4\n#" );
  fwrite( cab,1,strlen( cab ),f );
  if( docn != NULL ) fwrite( docn,1,strlen( docn ), f );
  sprintf( cab,"\n%d %d\n",GrSizeX(),GrSizeY() );
  fwrite( cab,1,strlen( cab ),f );
  for( y=0; y<GrSizeY(); y++ ){
    for( x=0; x<GrSizeX(); x++ ){
      if( GrPixel( x,y ) == GrBlack() )
        currentbyte |= 1 << currentbit;
      currentbit--;
      if( currentbit < 0 ){
        fwrite( &currentbyte,1,1,f );
        currentbyte = 0;
        currentbit = 7;
        }
      }
    if( currentbit < 7 ){
      fwrite( &currentbyte,1,1,f );
      currentbyte = 0;
      currentbit = 7;
      }
    }
  GrSetContext( &grcaux );
  fclose( f );

  return 0;
}
Esempio n. 8
0
/* Initialize Grfx-Mode&Mouse.Try to use xres,yres,colors and font <fontname>.
   If you are successful, return a 1.
   If you can't initialize this mode, return a 0. */
int ws_initgrfx(int xres, int yres, int colors, const char *fontname) {
    static char pixels[2];
/* unsigned char value; 
    Why?  -jgk*/
    GrBitmap pat_bm = {
        0, 2, pixels, 1, 0, 0
    };


    if ( ( ws_private.textopt.txo_font =
              GrLoadFont( (char *)(fontname == NULL ?
                                   DEFAULT_FONT :
                                   fontname) ) ) == NULL ) {
        fprintf(errf, "Can't find font %s\n", fontname);
        return 0;
    }

    if ( !GrSetMode(GR_width_height_color_graphics, xres, yres, colors) ) {
        fprintf(errf, "Can't set grfx-mode. Try to load VESA-driver\n");
        return 0;
    }

    if (GrSizeX() != xres || GrSizeY() != yres) {
        fprintf(errf, "Can't set grfx-mode. Try to load VESA-driver\n");
        return 0;
    }

    GrClearScreen(0);

    if ( !GrMouseDetect() ) {
        fprintf(errf, "Can't find mouse\n");
        return 0;
    }

    GrMouseInit();
    GrMouseSetColors(255, 0);
    GrMouseDisplayCursor();
    pixels[0] = 0x79;   /* Prevent compiler warning for now */
    pixels[1] = 0x55;
    ws_private.pat_box.gp_bitmap = pat_bm;
/* value=_farpeekb(0x40,0x17);
   _farpokeb(0x40,0x17,value^0x20); */
    return 1;
}
Esempio n. 9
0
/* Create bitmap with bm inside. */
struct ws_bitmap *ws_createbitmap(int xsize, int ysize, char *bm) {
    GrContext *gc;
    struct ws_bitmap *bmap;
    char *mem[4];


    if (bm != NULL) {
        mem[0] = bm;
        mem[1] = mem[2] = mem[3] = NULL;
    }

    if ( xsize < 0 || ysize < 0 || xsize > GrSizeX() || ysize > GrSizeY() ) {
        return NULL;
    }

    if ( ( bmap = MALLOC( sizeof(struct ws_bitmap) ) ) == NULL ) {
        return NULL;
    }

    if ( ( gc =
              GrCreateContext(xsize, ysize, bm != NULL ? mem : NULL,
                              NULL) ) == NULL ) {
        FREE(bmap);
        return NULL;
    }

    if (bm == NULL) {
        GrSetContext(gc);
        GrClearContext(notes.colindex[cv_winfill]);
        GrSetContext(NULL);
    }

    bmap->bitmap = (void *)gc;
    bmap->xpos = 0;
    bmap->ypos = 0;
    bmap->xsize = xsize;
    bmap->ysize = ysize;
    bmap->w = NULL;
    return bmap;
}
Esempio n. 10
0
static int writepng( FILE *f, GrContext *grc )
{
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 height;
  png_uint_32 width;
  png_byte *png_pixels = NULL;
  png_byte **row_pointers = NULL;
  png_byte *pix_ptr = NULL;
  int x, y, r, g, b;
  GrColor *pColors = NULL;

  /* Create and initialize the png_struct */
  png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL );
  if( png_ptr == NULL )
    return -1;

  /* Allocate/initialize the image information data */
  info_ptr = png_create_info_struct( png_ptr );
  if( info_ptr == NULL ){
    png_destroy_write_struct( &png_ptr,(png_infopp)NULL );
    return -1;
    }

  /* Set error handling */
  if( setjmp( png_jmpbuf(png_ptr) ) ){
    /* If we get here, we had a problem reading the file */
    png_destroy_write_struct( &png_ptr,&info_ptr );
    return -1;
    }

  /* set up the output control we are using standard C streams */
  png_init_io( png_ptr,f );

  /* Set the image information  */
  width = GrSizeX();
  height = GrSizeY();
  png_set_IHDR( png_ptr,info_ptr,width,height,8,PNG_COLOR_TYPE_RGB,
                PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE );

  /* No gamma correction by now */
  /* png_set_gAMA(png_ptr, info_ptr, gamma); */

  /* No comments by now */
  /* text_ptr[0].key = "Title";
   text_ptr[0].text = "Mona Lisa";
   text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
   text_ptr[1].key = "Author";
   text_ptr[1].text = "Leonardo DaVinci";
   text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
   text_ptr[2].key = "Description";
   text_ptr[2].text = "<long text>";
   text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
   png_set_text(png_ptr, info_ptr, text_ptr, 3); */

  /* Write the file header information */
  png_write_info( png_ptr,info_ptr );

  png_pixels = (png_byte *) malloc( width * 3 * sizeof(png_byte) );
  if( png_pixels == NULL ){
    png_destroy_write_struct( &png_ptr,&info_ptr );
    return -1;
    }

  row_pointers = (png_byte **) malloc( 1 * sizeof(png_bytep) );
  if( row_pointers == NULL ){
    png_destroy_write_struct( &png_ptr,&info_ptr );
    free( png_pixels );
    return -1;
    }

  pColors = malloc( width * sizeof(GrColor) );
  if( pColors == NULL ){
    png_destroy_write_struct( &png_ptr,&info_ptr );
    free( row_pointers );
    free( png_pixels );
    return -1;
    }

  row_pointers[0] = png_pixels;

  for( y=0; y<height; y++ ){
    pix_ptr = png_pixels;
    memcpy( pColors,GrGetScanline( 0,width-1,y ),sizeof(GrColor)*width );
    for( x=0; x<width; x++ ){
      GrQueryColor( pColors[x],&r,&g,&b );
      *pix_ptr++ = r;
      *pix_ptr++ = g;
      *pix_ptr++ = b;
      }
    png_write_rows( png_ptr,&row_pointers[0],1 );
    }

  /* It is REQUIRED to call this to finish writing the rest of the file */
  png_write_end( png_ptr,info_ptr );

  /* clean up after the write, and free any memory allocated */
  png_destroy_write_struct( &png_ptr,&info_ptr );
  free( pColors );
  free( row_pointers );
  free( png_pixels );

  return 0;
}
Esempio n. 11
0
static int readpng( FILE *f, GrContext *grc, int use_alpha )
{
  png_struct *png_ptr = NULL;
  png_info *info_ptr = NULL;
  png_byte buf[8];
  png_byte *png_pixels = NULL;
  png_byte **row_pointers = NULL;
  png_byte *pix_ptr = NULL;
  png_uint_32 row_bytes;
  png_uint_32 width;
  png_uint_32 height;
  int bit_depth;
  int color_type;
  int alpha_present;
  int i, x, y, r, g, b;
  int alpha = 0, ro, go, bo;
  int maxwidth, maxheight;
  GrColor *pColors = NULL;

  /* is it a PNG file? */
  if( fread( buf,1,8,f ) != 8 ) return -1;
  if( ! png_check_sig( buf,8 ) ) return -1;

  png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  if( !png_ptr ){
    return -1;
    }

  info_ptr = png_create_info_struct( png_ptr );
  if( !info_ptr ){
    png_destroy_read_struct( &png_ptr,NULL,NULL );
    return -1;
    }

  if( setjmp( png_jmpbuf(png_ptr) ) ){
    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    return -1;
    }

  png_init_io( png_ptr,f );
  png_set_sig_bytes( png_ptr,8 );
  png_read_info( png_ptr,info_ptr );

  png_get_IHDR( png_ptr,info_ptr,&width,&height,&bit_depth,
                &color_type,NULL,NULL,NULL);

  /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  if( bit_depth == 16 )
    png_set_strip_16( png_ptr );
  /* expand paletted colors into true RGB triplets */
  if( color_type == PNG_COLOR_TYPE_PALETTE )
    png_set_expand( png_ptr );
  /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
    png_set_expand( png_ptr );
  /* expand paletted or RGB images with transparency to full alpha channels
     so the data will be available as RGBA quartets. */
  if( png_get_valid( png_ptr,info_ptr,PNG_INFO_tRNS ) )
    png_set_expand( png_ptr );
  /* transform grayscale images into rgb */
  if( color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
    png_set_gray_to_rgb( png_ptr );

  /* we don't do gamma correction by now */

  png_read_update_info( png_ptr,info_ptr );
  png_get_IHDR( png_ptr,info_ptr,&width,&height,&bit_depth,
                &color_type,NULL,NULL,NULL);

  if( color_type == PNG_COLOR_TYPE_RGB )
    alpha_present = 0;
  else if( color_type == PNG_COLOR_TYPE_RGB_ALPHA )
    alpha_present = 1;
  else{
    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    return -1;
    }

  row_bytes = png_get_rowbytes( png_ptr,info_ptr );

  png_pixels = (png_byte *) malloc( row_bytes * height * sizeof(png_byte) );
  if( png_pixels == NULL ){
    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    return -1;
    }

  row_pointers = (png_byte **) malloc( height * sizeof(png_bytep) );
  if( row_pointers == NULL ){
    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    free( png_pixels );
    png_pixels = NULL;
    return -1;
    }

  for( i=0; i<height; i++ )
    row_pointers[i] = png_pixels + i * row_bytes;

  png_read_image (png_ptr, row_pointers);

  png_read_end (png_ptr, info_ptr);

  png_destroy_read_struct( &png_ptr,&info_ptr,NULL );

  /* write data to context */
  maxwidth = (width > GrSizeX()) ? GrSizeX() : width;
  maxheight = (height > GrSizeY()) ? GrSizeY() : height;

  pColors = malloc( maxwidth * sizeof(GrColor) );
  if( pColors == NULL ){
    free( row_pointers );
    row_pointers = NULL;
    free( png_pixels );
    png_pixels = NULL;
    return -1;
    }

  for( y=0; y<maxheight; y++ ){
    pix_ptr = row_pointers[y];
    if( alpha_present && use_alpha ){
      memcpy( pColors,GrGetScanline( 0,maxwidth-1,y ),
              sizeof(GrColor)*maxwidth );
      }
    for( x=0; x<width; x++ ){
      r = *pix_ptr++;
      g = *pix_ptr++;
      b = *pix_ptr++;
      alpha = 0;
      if( alpha_present )
        alpha = *pix_ptr++;
      if( x < maxwidth ){
        if( alpha_present && use_alpha ){
          if (alpha == 0) {
            GrQueryColor( pColors[x],&r,&g,&b );
          }
          else if (alpha != 255) { // if a==255, rgb not modified
            float f1, f2;
            f1 = (alpha/255.0);
            f2 = ((255-alpha)/255.0);
            GrQueryColor( pColors[x],&ro,&go,&bo );
            r = (r * f1) + (ro * f2);
            g = (g * f1) + (go * f2);
            b = (b * f1) + (bo * f2);
          }
        }
        pColors[x] = GrAllocColor( r,g,b );
        }
      }
    GrPutScanline( 0,maxwidth-1,y,pColors,GrWRITE );
    }

  if( pColors) free( pColors );
  if( row_pointers ) free( row_pointers );
  if( png_pixels ) free( png_pixels );

  return 0;
}
Esempio n. 12
0
int main(int argc, char **argv)
{
	int i, n;
	char *s;
	char *bad = NULL;
	int c;

	int width = 0, height = 0, bpp = 8, gray = 192, attributes = 0;

	char *name, *testname;
	GrFontHeader *hdr;
	FILE *f;
	char buffer[210];
	GrEvent ev;
	int key;

	/* unfortunately not all systems support getopt() */
	for(i = 1; i < argc; i++) {
	    s = argv[i];
	    if(*s != '-' || ((c = *++s) == '\0') || *++s != '\0') break;
	    if(c == '-') {
		i++;
		break;
	    }
	    if(++i == argc) {
		fprintf(stderr, "-%c: argument required\n", c);
		return(1);
	    }
	    if(sscanf(argv[i], "%d", &n) != 1 || n < 0) {
		fprintf(stderr, "%s: invalid argument\n", argv[i]);
		exit(1);
	    }
	    switch(c) {
		case 'x' : width = n; break;
		case 'y' : height = n; break;
		case 'b' : if((bpp = n) < 2 || bpp > 32) bad = "bpp"; break;
		case 'g' : if((gray = n) > 255) bad = "gray"; break;
		case 'X' : if((deltax = n) > 31) bad = "deltax"; break;
		case 'Y' : if((deltax = n) > 31) bad = "deltay"; break;
		case 'a' : if((attributes = n) > 3) bad = "attributes"; break;
		default  : {
		    fprintf(stderr, "-%c: invalid option\n", c);
		    return(1);
		}
	    }
	    if(bad) {
		fprintf(stderr, "%d: %s out of range\n", n, bad);
		return(1);
	    }
	}

	if(i == argc) {
	    printf(
		"usage:\tfontdemo [-x WIDTH] [-y HEIGHT] [-b BPP] [-g COMPONENT]\n"
		      "\t[-X DELTAX] [-Y DELTAY] [-a ATTRIBUTES] FONT [FILE...]\n"
	    );
	    return(0);
	}

	name = argv[i++];
	opt.txo_font = GrLoadFont(name);
        if(opt.txo_font == NULL && (testname = malloc(strlen(name) + 10)) != NULL) {
            /* try again, this is a test and the path can not been set yet */
#if defined(__MSDOS__) || defined(__WIN32__)
            sprintf( testname,"..\\fonts\\%s",name );
#else
            sprintf( testname,"../fonts/%s",name );
#endif
            opt.txo_font = GrLoadFont(testname);
	    free(testname);
        }
	if(opt.txo_font == NULL) {
	    fprintf(stderr, "%s: load error\n", name);
	    return(1);
	}
	hdr = &opt.txo_font->h;

	if(height == 0) {
	    if(width == 0) {
		switch(hdr->height) {
		    case 8 :
		    case 14 : height = 400; break;
		    case 16 : height = 480; break;
		    case 20 : height = 600; break;
		    case 24 : height = 768; break;
		    default : height = hdr->height < 20 ? 480 : 768;
		}
	    }
	    else height = width * 3 / 4;
	}
	if(width == 0) width = height == 400 ? 640 : height * 4 / 3;

	GrSetMode(GR_width_height_bpp_graphics, width, height, bpp);
	if(!gray || (opt.txo_fgcolor.v = GrAllocColor(gray, gray, gray)) == GrNOCOLOR) opt.txo_fgcolor.v = GrWhite();
	if(attributes & 0x02) opt.txo_fgcolor.v |= GR_UNDERLINE_TEXT;
	opt.txo_bgcolor.v = GrBlack();
	if(attributes & 0x01) revert();
	opt.txo_chrtype = GR_BYTE_TEXT;
	opt.txo_direct = GR_TEXT_RIGHT;
	opt.txo_xalign = GR_ALIGN_LEFT;
	opt.txo_yalign = GR_ALIGN_TOP;

	sprintf(buffer, "Font name:%s %dx%d", hdr->name, GrCharWidth('A', &opt), GrCharHeight('A', &opt));
        if (hdr->proportional)
	    strcat(buffer, " proportional");
	else
	    strcat(buffer, " fixed");
	gputs(buffer);
	sprintf(buffer, "Font family: %s", hdr->family);
	gputs(buffer);
	sprintf(buffer, "Min char, num chars: %d, %d", hdr->minchar,hdr->numchars);
	gputs(buffer);
	sprintf(buffer, "Screen res: %dx%d@%lu", GrSizeX(), GrSizeY(), (unsigned long) GrNumColors());
	gputs(buffer);
	gnewl();

	gputs("THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");
	gputs("the quick brown fox jumps over the lazy dog");
	gnewl();

//	if(hdr->minchar <= 0xC0 && hdr->minchar + hdr->numchars >= 0x100) {
//	    gputs("������� ��� ���� ���� ��");
//	    gputs("������� ��� ���� ���� ��");
//	    gnewl();
//	}

	/* ascii table, or to be precise, a full table of the current font */
	opt.txo_chrtype = GR_WORD_TEXT;
	for(c = 0; c < hdr->numchars; c++) {
	    gputc(hdr->minchar + c);
	    if(c % 0x20 == 0x1F) gnewl();
	}
	gnewl();
	if(c % 0x20 != 0) gnewl();
	opt.txo_chrtype = GR_BYTE_TEXT;

	while(i < argc) {
	    name = argv[i++];
	    if((f = fopen(name, "r")) == NULL) {
		perror(name);
		return(1);
	    }
	    while((c = getc(f)) != EOF) if(c != '\n') gputc(c); else gnewl();
	    if(ferror(f) != 0 || fclose(f) != 0) {
		perror(name);
		return(1);
	    }
	}

	/* enter and esc are < 0x100 and displayed 1:1 */
	gputs("F1-new line  F5-toggle reverse  F7-toggle underline  F10-exit");
	gnewl();

	GrEventInit();
	while(1) {
	    GrEventWait(&ev);
	    if(ev.type == GREV_KEY) {
		key = ev.p1;
		if( key == GrKey_F10) break;
		if(key == GrKey_F1) gnewl();
		else if(key == GrKey_F5) revert();
		else if(key == GrKey_F7) opt.txo_fgcolor.v ^= GR_UNDERLINE_TEXT;
		else if(key < 0x100) gputc(key);
	    }
	}
	GrEventUnInit();

	GrUnloadFont(opt.txo_font);

	return(0);
}