static char     sccsid[] = "@(#)xengine.c	1.10   10/2/90";

/*
 * xengine - reciprocating engine for X     :-)
 * 
 * Author: Kazuhiko Shutoh, 1990.
 * 
 * Permission to use, copy, modify and distribute without charge this software,
 * documentation, images, etc. is granted, provided that this comment and the
 * author's name is retained.  The author assumes no responsibility for lost
 * sleep as a consequence of use of this software.
 * 
 * Send any comments, bug reports, etc. to: shutoh@isl.yamaha.JUNET or, for
 * oversea: shutoh%isl.yamaha.JUNET%kddlab@uunet.uu.net
 * 
 */

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <math.h>

#include "patchlevel.h"

#define	PI	3.141592654

XtCallbackProc  redraw_callback();
XtTimerCallbackProc Cylcle();

Widget          toplevel, base, rpm_info, engine;
GC              gcPiston, gcShaft, gcCylinder, gcRoter, gcBack, gcDep, gcPre, gcEngine;
Pixmap          enginePixmap;
int             width, height;

String          colors[] = {"gray", "lightseagreen", "dimgrey", "forestgreen", "black", "red", "cyan", "firebrick"};

main(argc, argv)
	int             argc;
	char          **argv;
{

	Arg             args[10];
	XtTranslations  newTranslations;
	static XtActionsRec redrawActions[] = {
		{"expose", (XtCallbackProc) redraw_callback},
	};

	static char    *overrideTranslations =
	"<Expose>:	expose() \n\
	 <ResReq>:	expose()";

	XColor          srcColor, dummyColor;

	int             i;
	int             count;

	XtTimerCallbackProc Cycle();

	toplevel = XtInitialize("xengine", "XEngine", NULL, 0, &argc, argv);

	for (count = 1; count < argc; count++) {
		if ((strcmp("-piston", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[0], argv[++count]);
		else if ((strcmp("-shaft", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[1], argv[++count]);
		else if ((strcmp("-cylinder", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[2], argv[++count]);
		else if ((strcmp("-roter", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[3], argv[++count]);
		else if ((strcmp("-back", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[4], argv[++count]);
		else if ((strcmp("-dep", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[5], argv[++count]);
		else if ((strcmp("-pre", argv[count]) == 0) && (count + 1 <= argc))
			strcpy(colors[6], argv[++count]);
		else if ((strcmp("-patchlevel", argv[count]) == 0) && (count + 1 <= argc))
		  {
		  printf("xengine - written by Kazuhiko Shutoh\nSCCS ID : %s\nPatchlevel : %d\n", sccsid, PATCHLEVEL);
		  exit(0);
		}
		else if ((strcmp("-mono", argv[count]) == 0) && (count + 1 <= argc)) {
			for (i = 0; i < 8; i++)
				strcpy(colors[i], "white");
			strcpy(colors[4], "black");
		} else {
			fprintf(stderr, "Usage : xengine [Toolkit-Options][-piston piston_color][-shaft shaft_color][-cylinder cylinder_color][-roter roter_color][-back background_color][-dep depression_colore][-pre pression color][-mono][-patchlevel]\n");
			exit(0);
		}
	}

	base = XtCreateManagedWidget("base", formWidgetClass, toplevel, NULL, 0);

	i = 0;
	XtSetArg(args[i], XtNwidth, 200);
	i++;
	XtSetArg(args[i], XtNheight, 200);
	i++;
	engine = XtCreateManagedWidget("engine", boxWidgetClass, base, args, i);
	width = height = 200;

	i = 0;
	XtSetArg(args[i], XtNfromHoriz, engine);
	i++;
	XtSetArg(args[i], XtNheight, 200);
	i++;
	rpm_info = XtCreateManagedWidget("rpm_info", asciiTextWidgetClass, base, args, i);

	XtAddActions(redrawActions, XtNumber(redrawActions));
	newTranslations = XtParseTranslationTable(overrideTranslations);
	XtOverrideTranslations(engine, newTranslations);

	XtRealizeWidget(toplevel);

	/* Get graphic context	 */

	gcPiston = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[0], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcPiston, srcColor.pixel);

	gcShaft = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[1], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcShaft, srcColor.pixel);
	XSetLineAttributes(XtDisplay(engine), gcShaft, 2, LineSolid, CapButt, JoinMiter);

	gcCylinder = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XSetGraphicsExposures(XtDisplay(engine), gcCylinder, False);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[2], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcCylinder, srcColor.pixel);

	gcRoter = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[3], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcRoter, srcColor.pixel);

	gcBack = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[4], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcBack, srcColor.pixel);

	gcDep = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[5], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcDep, srcColor.pixel);

	gcPre = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[6], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcPre, srcColor.pixel);

	gcEngine = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL);
	XAllocNamedColor(XtDisplay(engine), DefaultColormapOfScreen(XtScreen(engine)), colors[7], &srcColor, &dummyColor);

	XSetForeground(XtDisplay(engine), gcEngine, srcColor.pixel);

	/* Create engine Pixmap */

	enginePixmap = XCreatePixmap(XtDisplay(engine), XtWindow(engine), width, height, DefaultDepthOfScreen(XtScreen(engine)));

	/* Interval timer start	 */
	XtAddTimeOut(1, Cycle, NULL);

	XtMainLoop();
}

XtCallbackProc
redraw_callback(w, event, params, nparams)
	Widget          w;
	XEvent         *event;
	String         *params;
	Cardinal       *nparams;
{

	Arg             args[10];

	XtSetArg(args[0], XtNwidth, &width);
	XtSetArg(args[1], XtNheight, &height);
	XtGetValues(w, args, 2);

	XFreePixmap(XtDisplay(engine), enginePixmap);
	enginePixmap = XCreatePixmap(XtDisplay(engine), XtWindow(engine), width, height, DefaultDepthOfScreen(XtScreen(engine)));

}

XtTimerCallbackProc
Cycle(client_data, id)
	caddr_t         client_data;
	XtIntervalId    id;
{

	Arg             args[10];
	static char     label[256];
	char            tmp_str[16];
	static int      i = 0;
	static int      sample_count = 0;
	static double   mean = 0.0;
	double          DrawEngine();

	if (i++ > 10) {
		sprintf(tmp_str, "%4.1f rpm\n", mean / 10.0);

		if (sample_count++ > 14) {
			strcpy(label, "");
			sample_count = 0;
		}
		strcat(label, tmp_str);
		XtSetArg(args[0], XtNstring, label);
		XtSetValues(rpm_info, args, 1);
		i = 0;
		mean = 0.0;
	}
	mean += DrawEngine();
	XtAddTimeOut(1, Cycle, NULL);
}

double
DrawEngine()
{

	double          cycle;
	static int      sw = 1;
	double          angle, theta;
	double          piston_x1, piston_y1;
	double          piston_x2, piston_y2;
	struct timeval  start, end;
	struct timezone dummy;

	sw ^= 1;

	XSync(XtDisplay(engine), 0);
	gettimeofday(&start, &dummy);
	for (angle = -180; angle < 180; angle += 18) {
		theta = angle * (PI / 180.0);
		piston_x1 = sin(theta) * (width * 0.1) + (width / 2);
		piston_y1 = cos(theta) * (height * 0.1) + (height * 0.7);
		piston_x2 = width / 2;
		piston_y2 = piston_y1 - (height * 0.3);

		/* Crear Window */

		XFillRectangle(XtDisplay(engine), enginePixmap, gcBack, 0, 0, width, height);

		/* Draw heat sink */

		XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine,
			       (int) (width * 0.35), (int) (height * 0.3),
			       (int) (width * 0.3), (int) (height * 0.02));

		XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine,
			       (int) (width * 0.35), (int) (height * 0.35),
			       (int) (width * 0.3), (int) (height * 0.02));

		XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine,
			       (int) (width * 0.35), (int) (height * 0.4),
			       (int) (width * 0.3), (int) (height * 0.02));

		/* Draw Cylinder */

		XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine,
			       (int) (width * 0.42), (int) (height * 0.24),
			       (int) (width * 0.16), (int) (height * 0.5));

		XFillArc(XtDisplay(engine), enginePixmap, gcEngine,
			 (int) (piston_x2 - (width * 0.15)), (int) ((height * 0.7) - (height * 0.15)), (int) (width * 0.3), (int) (height * 0.3), 0 * 64, 360 * 64);

		XFillArc(XtDisplay(engine), enginePixmap, gcBack,
			 (int) (piston_x2 - (width * 0.14)), (int) ((height * 0.7) - (height * 0.14)), (int) (width * 0.28), (int) (height * 0.28), 0 * 64, 360 * 64);

		XFillRectangle(XtDisplay(engine), enginePixmap, gcBack,
			       (int) (width * 0.43), (int) (height * 0.25),
			       (int) (width * 0.14), (int) (height * 0.5));

		/* Draw Gas */

		if (sw != 0) {
			XFillRectangle(XtDisplay(engine), enginePixmap, gcPre,
			       (int) (width * 0.435), (int) (height * 0.25),
				       (int) (width * 0.13), (int) (piston_y2 - (height * 0.05) - (height * 0.26) + (height * 0.1)));
		} else {
			XFillRectangle(XtDisplay(engine), enginePixmap, gcDep,
			       (int) (width * 0.435), (int) (height * 0.25),
				       (int) (width * 0.13), (int) (piston_y2 - (height * 0.05) - (height * 0.26) + (height * 0.1)));
		}

		/* Draw Piston arm */

		XDrawLine(XtDisplay(engine), enginePixmap, gcShaft,
			  (int) piston_x1, (int) piston_y1, (int) piston_x2, (int) piston_y2);
		XDrawLine(XtDisplay(engine), enginePixmap, gcShaft,
			  (int) piston_x1, (int) piston_y1, (int) piston_x2, (int) (height * 0.7));


		/* Draw Piston & ring */

		XFillRectangle(XtDisplay(engine), enginePixmap, gcPiston,
		 (int) (width * 0.435), (int) (piston_y2 - (height * 0.05)),
			       (int) (width * 0.13), (int) (height * 0.1));

		XFillRectangle(XtDisplay(engine), enginePixmap, gcShaft,
		(int) (width * 0.435), (int) (piston_y2 - (height * 0.045)),
			       (int) (width * 0.13), (int) (height * 0.01));

		XFillArc(XtDisplay(engine), enginePixmap, gcShaft,
			 (int) (piston_x2 - (width * 0.015)), (int) (piston_y2 - (height * 0.015)), (int) (width * 0.03), (int) (height * 0.03), 0, 360 * 64);

		/* Draw Roter */
		XFillArc(XtDisplay(engine), enginePixmap, gcRoter,
			 (int) (piston_x2 - (width * 0.1)), (int) ((height * 0.7) - (height * 0.1)), (int) (width * 0.2), (int) (height * 0.2), (int) (angle + 30) * 64, 120 * 64);

		XFillArc(XtDisplay(engine), enginePixmap, gcPiston,
			 (int) (piston_x2 - (width * 0.025)), (int) ((height * 0.7) - (height * 0.025)), (int) (width * 0.05), (int) (height * 0.05), 0, 360 * 64);

		XCopyArea(XtDisplay(engine), enginePixmap, XtWindow(engine), gcCylinder, 0, 0, width, height, 0, 0);
	}

	XSync(XtDisplay(engine), 0);
	gettimeofday(&end, &dummy);

	cycle = 60 / ((double) ((end.tv_sec * 1000000 + end.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000);


	return (cycle);

}





syntax highlighted by Code2HTML, v. 0.9.1