/* * Copyright 1989 O'Reilly and Associates, Inc. * See ../Copyright for complete rights and liability information. * * This program has been altered to use Japanese fonts.  It does not * correctly display Japanese text because there are several character * sets in use, and the one my text editor uses is not the same as the * JIS standard.  But it does crash my DV/X server :-) *     To just switch fonts to a kanji font, #define JFONT. *     The icon bitmap has been included in the text of this program. * Other alterations are flagged by "#ifdef USE_JAPANESE".  Note:  the * strings include Japanese text, and therefore you need an 8-bit capable * text editor to avoid getting spurious control characters etc.  However, * I am fairly sure that there are no nulls.  Of course, if your editor * doesn't handle Japanese, it will be garbage, but if you don't have a * Japanese text editor, you probably can't read Japanese anyway ;-) *     Other includes are standard with X or C. */#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/Xatom.h>#include <stdio.h>#define icon_bitmap_width 40#define icon_bitmap_height 40static char icon_bitmap_bits[] = {   0xc3, 0xc3, 0x7f, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,   0x00, 0x00, 0x80, 0x38, 0x00, 0x40, 0x00, 0x80, 0x24, 0x00, 0x00, 0x00,   0x80, 0x44, 0x00, 0x00, 0x00, 0x80, 0x44, 0x00, 0x00, 0x00, 0x80, 0x74,   0x00, 0x0f, 0x0c, 0x00, 0x7c, 0x3e, 0x41, 0x0e, 0x00, 0x44, 0x22, 0x41,   0x02, 0x00, 0x84, 0x22, 0x46, 0x02, 0x00, 0x9c, 0x26, 0xcc, 0x02, 0x00,   0x78, 0x3c, 0xcd, 0x36, 0x80, 0x00, 0x20, 0x06, 0x0c, 0x80, 0x01, 0x00,   0x00, 0x00, 0x80, 0x01, 0x02, 0x40, 0x00, 0x80, 0x01, 0x06, 0x40, 0x00,   0x80, 0x01, 0x04, 0x20, 0x00, 0x80, 0x01, 0x04, 0x20, 0x01, 0x80, 0x01,   0x04, 0x20, 0x00, 0x80, 0x01, 0x04, 0x22, 0x00, 0x80, 0x01, 0x04, 0x33,   0xf1, 0x81, 0x01, 0x88, 0x12, 0x31, 0x03, 0x01, 0x88, 0x12, 0x11, 0x02,   0x00, 0x88, 0x12, 0x11, 0x02, 0x00, 0x48, 0x1a, 0x11, 0x02, 0x00, 0x70,   0x04, 0x19, 0x82, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x38,   0x80, 0x01, 0x00, 0x00, 0xce, 0x80, 0x01, 0x00, 0x00, 0x83, 0x81, 0x81,   0x07, 0x80, 0x01, 0x81, 0xe1, 0x04, 0xc0, 0x00, 0x83, 0x31, 0x08, 0x40,   0x00, 0x82, 0x10, 0x08, 0x20, 0x00, 0x82, 0x19, 0x10, 0x30, 0x00, 0x86,   0x0c, 0x30, 0x18, 0x00, 0x84, 0x04, 0x60, 0x0e, 0x00, 0xdc, 0x02, 0x80,   0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00};/* To use original English messages, remove definition of USE_JAPANESE *//* #define USE_JAPANESE */#ifdef USE_JAPANESE#define JFONT#endif#define BITMAPDEPTH 1#define TOO_SMALL 0#define BIG_ENOUGH 1/* These are used as arguments to nearly every Xlib routine, so it saves  * routine arguments to declare them global.  If there were  * additional source files, they would be declared extern there. */Display *display;int screen_num;static char *progname; /* name this program was invoked by */void main(argc, argv)int argc;char **argv;{	Window win;	unsigned int width, height;	/* window size */	int x, y; 	/* window position */	unsigned int border_width = 4;	/* four pixels */	unsigned int display_width, display_height;	unsigned int icon_width, icon_height;#if 0	XChar2b *window_name = (XChar2b *) "基本窓プログラム";	XChar2b *icon_name = (XChar2b *) "ベ−シックウイン";#else	char *window_name = "Basic Window Program";	char *icon_name = "basicwin";#endif	Pixmap icon_pixmap;	XSizeHints *size_hints;	XIconSize *size_list;	XWMHints *wm_hints;	XClassHint *class_hints;	XTextProperty windowName, iconName;	int count;	XEvent report;	GC gc;	XFontStruct *font_info;	char *display_name = NULL;	int window_size = BIG_ENOUGH;	/* or TOO_SMALL to display contents */	if (!(size_hints = XAllocSizeHints())) {		fprintf(stderr, "%s: failure allocating memory\n", progname);        exit(0);    }	if (!(wm_hints = XAllocWMHints())) {		fprintf(stderr, "%s: failure allocating memory\n", progname);        exit(0);    }	if (!(class_hints = XAllocClassHint())) {		fprintf(stderr, "%s: failure allocating memory\n", progname);        exit(0);    }	progname = argv[0];	/* connect to X server */	if ( (display=XOpenDisplay(display_name)) == NULL )	{		(void) fprintf( stderr, "%s: cannot connect to X server %s\n", 				progname, XDisplayName(display_name));		exit( -1 );	}	/* get screen size from display structure macro */	screen_num = DefaultScreen(display);	display_width = DisplayWidth(display, screen_num);	display_height = DisplayHeight(display, screen_num);	/* Note that in a real application, x and y would default to 0	 * but would be settable from the command line or resource database.  	 */	x = y = 0;	/* size window with enough room for text */#ifdef USE_JAPANESE	/* The Japanese font I use is bigger */	width = 2*display_width/5, height = display_height/3;#else	width = display_width/3, height = display_height/4;#endif	/* create opaque window */	win = XCreateSimpleWindow(display, RootWindow(display,screen_num), 			x, y, width, height, border_width, BlackPixel(display,			screen_num), WhitePixel(display,screen_num));	/* Get available icon sizes from Window manager */	if (XGetIconSizes(display, RootWindow(display,screen_num), 			&size_list, &count) == 0)		(void) fprintf( stderr, "%s: Window manager didn't set icon sizes - using default.\n", progname);	else {		;		/* A real application would search through size_list		 * here to find an acceptable icon size, and then		 * create a pixmap of that size.  This requires		 * that the application have data for several sizes		 * of icons. */	}	/* Create pixmap of depth 1 (bitmap) for icon */	icon_pixmap = XCreateBitmapFromData(display, win, icon_bitmap_bits, 			icon_bitmap_width, icon_bitmap_height);	/* Set size hints for window manager.  The window manager may	 * override these settings.  Note that in a real	 * application if size or position were set by the user	 * the flags would be UPosition and USize, and these would	 * override the window manager's preferences for this window. */	/* x, y, width, and height hints are now taken from	 * the actual settings of the window when mapped. Note	 * that PPosition and PSize must be specified anyway. */	size_hints->flags = PPosition | PSize | PMinSize;#ifdef USE_JAPANESE	size_hints->min_width = 350;	size_hints->min_height = 250;#else	size_hints->min_width = 300;	size_hints->min_height = 200;#endif	/* These calls store window_name and icon_name into	 * XTextProperty structures and set their other 	 * fields properly. */	if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) {		(void) fprintf( stderr, "%s: structure allocation for windowName failed.\n", 				progname);		exit(-1);	}			if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) {		(void) fprintf( stderr, "%s: structure allocation for iconName failed.\n", 				progname);		exit(-1);	}	wm_hints->initial_state = NormalState;	wm_hints->input = True;	wm_hints->icon_pixmap = icon_pixmap;	wm_hints->flags = StateHint | IconPixmapHint | InputHint;	class_hints->res_name = progname;	class_hints->res_class = "Basicwin";	XSetWMProperties(display, win, &windowName, &iconName, 			argv, argc, size_hints, wm_hints, 			class_hints);	/* Select event types wanted */	XSelectInput(display, win, ExposureMask | KeyPressMask | 			ButtonPressMask | StructureNotifyMask);	load_font(&font_info);	/* create GC for text and drawing */	getGC(win, &gc, font_info);	/* Display window */	XMapWindow(display, win);	/* get events, use first to display text and graphics */	while (1)  {		XNextEvent(display, &report);		switch  (report.type) {		case Expose:			/* unless this is the last contiguous expose,			 * don't draw the window */			if (report.xexpose.count != 0)				break;			/* if window too small to use */			if (window_size == TOO_SMALL)				TooSmall(win, gc, font_info);			else {				/* place text in window */				draw_text(win, gc, font_info, width, height);				/* place graphics in window, */				draw_graphics(win, gc, width, height);			}			break;		case ConfigureNotify:			/* window has been resized, change width and			 * height to send to draw_text and draw_graphics			 * in next Expose */			width = report.xconfigure.width;			height = report.xconfigure.height;			if ((width < size_hints->min_width) || 					(height < size_hints->min_height))				window_size = TOO_SMALL;			else				window_size = BIG_ENOUGH;			break;		case ButtonPress:			/* trickle down into KeyPress (no break) */		case KeyPress:			XUnloadFont(display, font_info->fid);			XFreeGC(display, gc);			XCloseDisplay(display);			exit(1);		default:			/* all events selected by StructureNotifyMask			 * except ConfigureNotify are thrown away here,			 * since nothing is done with them */			break;		} /* end switch */	} /* end while */}getGC(win, gc, font_info)Window win;GC *gc;XFontStruct *font_info;{	unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */	XGCValues values;	unsigned int line_width = 6;	int line_style = LineOnOffDash;	int cap_style = CapRound;	int join_style = JoinRound;	int dash_offset = 0;	static char dash_list[] = {12, 24};	int list_length = 2;	/* Create default Graphics Context */	*gc = XCreateGC(display, win, valuemask, &values);	/* specify font */	XSetFont(display, *gc, font_info->fid);	/* specify black foreground since default window background is 	 * white and default foreground is undefined. */	XSetForeground(display, *gc, BlackPixel(display,screen_num));	/* set line attributes */	XSetLineAttributes(display, *gc, line_width, line_style, 			cap_style, join_style);	/* set dashes */	XSetDashes(display, *gc, dash_offset, dash_list, list_length);}load_font(font_info)XFontStruct **font_info;{#ifdef JFONT	char *fontname = "jis16";#else	char *fontname = "9x15";#endif	/* Load font and get font information structure. */	if ((*font_info = XLoadQueryFont(display,fontname)) == NULL)	{	        /* USE_JAPANESE - changed to parametrize the error */	        /* message with the font name                      */		(void) fprintf( stderr, "%s: Cannot open %s font\n", 				progname, fontname);		exit( -1 );	}}#ifdef USE_JAPANESE/* This is a rather impudent translation of basicwin's text into  *//* Japanese.  These are simply JIS-encoded strings.  I'm too lazy *//* to organize them according to XChar2b structure; this works.   */XChar2b anonymous1[] = {0x4b,0x4d,0x24,0x4f,0x41,0x6b,0x24,0x47,0x24,0x39,		       0x24,0x31,0x24,0x49,0x21,0x23,0x24,0x22,0x24,0x4a,		       0x24,0x3f,0x24,0x4f,0x24,0x40,0x24,0x6c,0x21,0x29,0,0};XChar2b anonymous2[] = {0x44,0x79,0x24,0x61,0x40,0x5a,0x24,0x6a,0x24,		       0x3f,0x24,0x2b,0x24,0x43,0x24,0x3f,0x24,0x69,0x41,		       0x6b,0x24,0x4b,0x25,0x5d,0x25,0x24,0x25,0x73,0x25,		       0x3f,0x24,0x72,0,0};XChar2b anonymous3[] = {0x39,0x67,0x24,0x6f,0x24,0x3b,0x24,0x46,0x25,0x5c,		       0x25,0x3f,0x25,0x73,0x4b,0x74,0x24,0x4f,0x25,0x2d,		       0x21,0x3d,0x24,0x72,0x32,0x21,0x24,0x37,0x24,0x46,		       0x32,0x3c,0x24,0x35,0x24,0x24,0x21,0x23,0,0};XChar2b anonymous4[] = {0x25,0x39,0x25,0x2f,0x25,0x6a,0x21,0x3d,0x25,0x73,		       0x25,0x35,0x25,0x24,0x25,0x3a,0x21,0x27,0,0};/* itoJIS translates an integer to a JIS-encoded string.  Returns the *//* string in a global buffer.  Buffer is protected against overflow,  *//* but in that case (25 digit integer or more), silently truncated.   */XChar2b itoJISbuffer[25];XChar2b *itoJIS (int i){  int first, last;  unsigned char byte;  /* write digits to buffer in reverse order */  for (last = 0; i && last < 24; ++last)    {      itoJISbuffer[last].byte1 = 0x23;      itoJISbuffer[last].byte2 = 0x30 + i%10;      i /= 10;    }  /* terminate string */  itoJISbuffer[last].byte1 = itoJISbuffer[last].byte2 = 0x00;  --last;  /* reverse string */  for (first = 0; first < last; ++first, --last)    {      byte = itoJISbuffer[first].byte2;      itoJISbuffer[first].byte2 = itoJISbuffer[last].byte2;      itoJISbuffer[last].byte2 = byte;    }  return itoJISbuffer;}#endifdraw_text(win, gc, font_info, win_width, win_height)Window win;GC gc;XFontStruct *font_info;unsigned int win_width, win_height;{#ifdef USE_JAPANESE	XChar2b *string1 = anonymous1;	XChar2b *string2 = anonymous2;	XChar2b *string3 = anonymous3;	XChar2b *string4 = anonymous4;#else	char *string1 = "Hi! I'm a window, who are you?";	char *string2 = "To terminate program; Press any key";	char *string3 = "or button while in this window.";	char *string4 = "Screen Dimensions:";#endif	int len1, len2, len3, len4;	int width1, width2, width3;#ifdef USE_JAPANESE	XChar2b cd_height[50] = {0x39,0x62,0x24,0x35,0x21,0x27,0x21,0x21,0,0},	        cd_width[50] = {0x39,0x2d,0x24,0x35,0x21,0x27,0x21,0x21,0,0},	        cd_depth[50] = {0x3f,0x3c,0x24,0x35,0x21,0x27,0x21,0x21,0,0},		cd_pixel[10] = {0x21,0x21,0x25,0x54,0x25,0x2f,0x25,0x3b,0x25,				  0x6b,0,0};#else	char cd_height[50], cd_width[50], cd_depth[50];#endif	int font_height;	int initial_y_offset, x_offset;	/* need length for both XTextWidth and XDrawString */        /* The cast is a no-op for English version, it works because */	/* there are no null bytes in JIS code under USE_JAPANESE. */	len1 = strlen((char *) string1);	len2 = strlen((char *) string2);	len3 = strlen((char *) string3);#ifdef USE_JAPANESE	len1 /= 2;	len2 /= 2;	len3 /= 2;#endif	/* get string widths for centering */#ifdef USE_JAPANESE	width1 = XTextWidth16(font_info, string1, len1);	width2 = XTextWidth16(font_info, string2, len2);	width3 = XTextWidth16(font_info, string3, len3);#else	width1 = XTextWidth(font_info, string1, len1);	width2 = XTextWidth(font_info, string2, len2);	width3 = XTextWidth(font_info, string3, len3);#endif	font_height = font_info->ascent + font_info->descent;#ifdef USE_JAPANESE	/* JIS fonts don't include vertical spacing */	font_height += 2;#endif	/* output text, centered on each line */#ifdef USE_JAPANESE	XDrawString16(display, win, gc, (win_width - width1)/2, 			font_height,			string1, len1);	XDrawString16(display, win, gc, (win_width - width2)/2, 			(int)(win_height - (2 * font_height)),			string2, len2);	XDrawString16(display, win, gc, (win_width - width3)/2, 			(int)(win_height - font_height),			string3, len3);#else	XDrawString(display, win, gc, (win_width - width1)/2, 			font_height,			string1, len1);	XDrawString(display, win, gc, (win_width - width2)/2, 			(int)(win_height - (2 * font_height)),			string2, len2);	XDrawString(display, win, gc, (win_width - width3)/2, 			(int)(win_height - font_height),			string3, len3);#endif	/* copy numbers into string variables */#ifdef USE_JAPANESE        /* usual trick of using string functions for JIS strings */        (void) strcat((char *) cd_height,		      (char *) itoJIS(DisplayHeight(display,screen_num)));        (void) strcat((char *) cd_width,		      (char *) itoJIS(DisplayWidth(display,screen_num)));        (void) strcat((char *) cd_depth,		      (char *) itoJIS(DefaultDepth(display,screen_num)));        (void) strcat((char *) cd_height, (char *) cd_pixel);        (void) strcat((char *) cd_width, (char *) cd_pixel);        (void) strcat((char *) cd_depth, (char *) cd_pixel);#else	(void) sprintf(cd_height, " Height - %d pixels", 			DisplayHeight(display,screen_num));	(void) sprintf(cd_width, " Width  - %d pixels", 			DisplayWidth(display,screen_num));	(void) sprintf(cd_depth, " Depth  - %d plane(s)", 			DefaultDepth(display, screen_num));#endif	/* reuse these for same purpose */	/* cast is no-op for English, usual trick for USE_JAPANESE */	len4 = strlen((char *) string4);	len1 = strlen((char *) cd_height);	len2 = strlen((char *) cd_width);	len3 = strlen((char *) cd_depth);#ifdef USE_JAPANESE        len1 /= 2;        len2 /= 2;        len3 /= 2;        len4 /= 2;#endif	/* To center strings vertically, we place the first string	 * so that the top of it is two font_heights above the center	 * of the window.  Since the baseline of the string is what we	 * need to locate for XDrawString, and the baseline is one	 * font_info->ascent below the top of the character,	 * the final offset of the origin up from the center of the 	 * window is one font_height + one descent. */	initial_y_offset = win_height/2 - font_height - font_info->descent;	x_offset = (int) win_width/4;#ifdef USE_JAPANESE	XDrawString16(display, win, gc, x_offset, (int) initial_y_offset, 			string4,len4);	XDrawString16(display, win, gc, x_offset, (int) initial_y_offset + 			font_height,cd_height,len1);	XDrawString16(display, win, gc, x_offset, (int) initial_y_offset + 			2 * font_height,cd_width,len2);	XDrawString16(display, win, gc, x_offset, (int) initial_y_offset + 			3 * font_height,cd_depth,len3);#else	XDrawString(display, win, gc, x_offset, (int) initial_y_offset, 			string4,len4);	XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 			font_height,cd_height,len1);	XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 			2 * font_height,cd_width,len2);	XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 			3 * font_height,cd_depth,len3);#endif}draw_graphics(win, gc, window_width, window_height)Window win;GC gc;unsigned int window_width, window_height;{	int x, y;	int width, height;	height = window_height/2;	width = 3 * window_width/4;	x = window_width/2 - width/2;  /* center */	y = window_height/2 - height/2;	XDrawRectangle(display, win, gc, x, y, width, height);}TooSmall(win, gc, font_info)Window win;GC gc;XFontStruct *font_info;{	char *string1 = "Too Small";	int y_offset, x_offset;	y_offset = font_info->ascent + 2;	x_offset = 2;	/* output text, centered on each line */	XDrawString(display, win, gc, x_offset, y_offset, string1, 			strlen(string1));}