blob: 22312bdcbe1c0aee002512fe39dc3a688da4652d [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -05002 * Copyright © 2008 Kristian Høgsberg
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
Kristian Høgsbergffd710e2008-12-02 15:15:01 -050021 */
22
Kristian Høgsberg96ce9682011-01-07 14:42:49 -050023#include "config.h"
24
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050025#include <stdint.h>
26#include <stdio.h>
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050027#include <stdlib.h>
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050028#include <string.h>
29#include <fcntl.h>
30#include <unistd.h>
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050031#include <math.h>
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050032#include <time.h>
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050033#include <glib.h>
34
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050035#include <GL/gl.h>
Kristian Høgsberg3afd45d2010-03-03 09:54:29 -050036#include <EGL/egl.h>
37#include <EGL/eglext.h>
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050038
Pekka Paalanen50719bc2011-11-22 14:18:50 +020039#include <wayland-client.h>
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050040
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050041#include "window.h"
42
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050043struct gears {
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050044 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050045 struct widget *widget;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050046
Kristian Høgsberg43c28ee2009-01-26 23:42:46 -050047 struct display *d;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050048
49 EGLDisplay display;
Benjamin Franzkecff904e2011-02-18 23:00:55 +010050 EGLDisplay config;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050051 EGLContext context;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050052 GLfloat angle;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050053
54 GLint gear_list[3];
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050055};
56
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050057struct gear_template {
58 GLfloat material[4];
59 GLfloat inner_radius;
60 GLfloat outer_radius;
61 GLfloat width;
62 GLint teeth;
63 GLfloat tooth_depth;
64};
65
66const static struct gear_template gear_templates[] = {
67 { { 0.8, 0.1, 0.0, 1.0 }, 1.0, 4.0, 1.0, 20, 0.7 },
68 { { 0.0, 0.8, 0.2, 1.0 }, 0.5, 2.0, 2.0, 10, 0.7 },
69 { { 0.2, 0.2, 1.0, 1.0 }, 1.3, 2.0, 0.5, 10, 0.7 },
70};
71
72static GLfloat light_pos[4] = {5.0, 5.0, 10.0, 0.0};
73
74static void die(const char *msg)
75{
76 fprintf(stderr, "%s", msg);
77 exit(EXIT_FAILURE);
78}
79
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050080static void
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050081make_gear(const struct gear_template *t)
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050082{
83 GLint i;
84 GLfloat r0, r1, r2;
85 GLfloat angle, da;
86 GLfloat u, v, len;
87
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050088 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->material);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050089
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -050090 r0 = t->inner_radius;
91 r1 = t->outer_radius - t->tooth_depth / 2.0;
92 r2 = t->outer_radius + t->tooth_depth / 2.0;
93
94 da = 2.0 * M_PI / t->teeth / 4.0;
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -050095
96 glShadeModel(GL_FLAT);
97
98 glNormal3f(0.0, 0.0, 1.0);
99
100 /* draw front face */
101 glBegin(GL_QUAD_STRIP);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500102 for (i = 0; i <= t->teeth; i++) {
103 angle = i * 2.0 * M_PI / t->teeth;
104 glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
105 glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
106 if (i < t->teeth) {
107 glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
108 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500109 }
110 }
111 glEnd();
112
113 /* draw front sides of teeth */
114 glBegin(GL_QUADS);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500115 da = 2.0 * M_PI / t->teeth / 4.0;
116 for (i = 0; i < t->teeth; i++) {
117 angle = i * 2.0 * M_PI / t->teeth;
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500118
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500119 glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
120 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
121 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
122 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500123 }
124 glEnd();
125
126 glNormal3f(0.0, 0.0, -1.0);
127
128 /* draw back face */
129 glBegin(GL_QUAD_STRIP);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500130 for (i = 0; i <= t->teeth; i++) {
131 angle = i * 2.0 * M_PI / t->teeth;
132 glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
133 glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
134 if (i < t->teeth) {
135 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
136 glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500137 }
138 }
139 glEnd();
140
141 /* draw back sides of teeth */
142 glBegin(GL_QUADS);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500143 da = 2.0 * M_PI / t->teeth / 4.0;
144 for (i = 0; i < t->teeth; i++) {
145 angle = i * 2.0 * M_PI / t->teeth;
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500146
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500147 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
148 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
149 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
150 glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500151 }
152 glEnd();
153
154 /* draw outward faces of teeth */
155 glBegin(GL_QUAD_STRIP);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500156 for (i = 0; i < t->teeth; i++) {
157 angle = i * 2.0 * M_PI / t->teeth;
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500158
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500159 glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
160 glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500161 u = r2 * cos(angle + da) - r1 * cos(angle);
162 v = r2 * sin(angle + da) - r1 * sin(angle);
163 len = sqrt(u * u + v * v);
164 u /= len;
165 v /= len;
166 glNormal3f(v, -u, 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500167 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
168 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500169 glNormal3f(cos(angle), sin(angle), 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500170 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
171 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500172 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
173 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
174 glNormal3f(v, -u, 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500175 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
176 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500177 glNormal3f(cos(angle), sin(angle), 0.0);
178 }
179
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500180 glVertex3f(r1 * cos(0), r1 * sin(0), t->width * 0.5);
181 glVertex3f(r1 * cos(0), r1 * sin(0), -t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500182
183 glEnd();
184
185 glShadeModel(GL_SMOOTH);
186
187 /* draw inside radius cylinder */
188 glBegin(GL_QUAD_STRIP);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500189 for (i = 0; i <= t->teeth; i++) {
190 angle = i * 2.0 * M_PI / t->teeth;
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500191 glNormal3f(-cos(angle), -sin(angle), 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500192 glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
193 glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500194 }
195 glEnd();
196}
197
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500198static void
Kristian Høgsberg5d129902012-01-10 10:49:41 -0500199frame_callback(void *data, struct wl_callback *callback, uint32_t time)
200{
201 struct gears *gears = data;
202
203 gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
204
205 window_schedule_redraw(gears->window);
206
207 if (callback)
208 wl_callback_destroy(callback);
209}
210
211static const struct wl_callback_listener listener = {
212 frame_callback
213};
214
215static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500216redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg2b43bd72010-11-08 15:45:55 -0500217{
Benjamin Franzkecff904e2011-02-18 23:00:55 +0100218 GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
219 struct rectangle window_allocation;
Kristian Høgsbergda846ca2011-01-11 10:00:52 -0500220 struct rectangle allocation;
Kristian Høgsberg5d129902012-01-10 10:49:41 -0500221 struct wl_callback *callback;
222 struct gears *gears = data;
Kristian Høgsberg2b43bd72010-11-08 15:45:55 -0500223
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500224 widget_get_allocation(gears->widget, &allocation);
Benjamin Franzkecff904e2011-02-18 23:00:55 +0100225 window_get_allocation(gears->window, &window_allocation);
Kristian Høgsberg2b43bd72010-11-08 15:45:55 -0500226
Benjamin Franzke1a89f282011-10-07 09:33:06 +0200227 if (display_acquire_window_surface(gears->d,
228 gears->window,
229 gears->context) < 0) {
230 die("Unable to acquire window surface, "
231 "compiled without cairo-egl?\n");
232 }
Benjamin Franzkecff904e2011-02-18 23:00:55 +0100233
234 glViewport(allocation.x,
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500235 window_allocation.height - allocation.height - allocation.y,
Kristian Høgsbergda846ca2011-01-11 10:00:52 -0500236 allocation.width, allocation.height);
Benjamin Franzkecff904e2011-02-18 23:00:55 +0100237 glScissor(allocation.x,
238 window_allocation.height - allocation.height - allocation.y,
239 allocation.width, allocation.height);
Kristian Høgsberg2b43bd72010-11-08 15:45:55 -0500240
241 glEnable(GL_SCISSOR_TEST);
Kristian Høgsberg78231c82008-11-08 15:06:01 -0500242 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Kristian Høgsbergb8bf19b2008-11-05 07:38:46 -0500243
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500244 glPushMatrix();
245
246 glTranslatef(0.0, 0.0, -50);
247
248 glRotatef(view_rotx, 1.0, 0.0, 0.0);
249 glRotatef(view_roty, 0.0, 1.0, 0.0);
250 glRotatef(view_rotz, 0.0, 0.0, 1.0);
251
252 glPushMatrix();
253 glTranslatef(-3.0, -2.0, 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500254 glRotatef(gears->angle, 0.0, 0.0, 1.0);
255 glCallList(gears->gear_list[0]);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500256 glPopMatrix();
257
258 glPushMatrix();
259 glTranslatef(3.1, -2.0, 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500260 glRotatef(-2.0 * gears->angle - 9.0, 0.0, 0.0, 1.0);
261 glCallList(gears->gear_list[1]);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500262 glPopMatrix();
263
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500264 glPushMatrix();
265 glTranslatef(-3.1, 4.2, 0.0);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500266 glRotatef(-2.0 * gears->angle - 25.0, 0.0, 0.0, 1.0);
267 glCallList(gears->gear_list[2]);
Kristian Høgsberg8a9cda82008-11-03 15:31:30 -0500268 glPopMatrix();
269
270 glPopMatrix();
271
272 glFlush();
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500273
Benjamin Franzke0c991632011-09-27 21:57:31 +0200274 display_release_window_surface(gears->d, gears->window);
Kristian Høgsberg5d129902012-01-10 10:49:41 -0500275
276 callback = wl_surface_frame(window_get_wl_surface(gears->window));
277 wl_callback_add_listener(callback, &listener, gears);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500278}
279
280static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500281resize_handler(struct widget *widget,
Kristian Høgsbergda846ca2011-01-11 10:00:52 -0500282 int32_t width, int32_t height, void *data)
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500283{
284 struct gears *gears = data;
285
Kristian Høgsbergda846ca2011-01-11 10:00:52 -0500286 /* Constrain child size to be square and at least 300x300 */
287 if (width > height)
288 height = width;
289 else
290 width = height;
291 if (width < 300) {
292 width = 300;
293 height = 300;
294 }
295
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500296 widget_set_size(gears->widget, width, height);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500297}
298
299static void
Kristian Høgsberg9ae561d2009-09-21 13:47:53 -0400300keyboard_focus_handler(struct window *window,
Kristian Høgsberg43788b12010-07-28 23:50:12 -0400301 struct input *device, void *data)
Kristian Høgsberg9ae561d2009-09-21 13:47:53 -0400302{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500303 window_schedule_redraw(window);
Kristian Høgsberg2b43bd72010-11-08 15:45:55 -0500304}
305
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500306static struct gears *
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400307gears_create(struct display *display)
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500308{
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500309 const int width = 450, height = 500;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500310 struct gears *gears;
311 int i;
312
313 gears = malloc(sizeof *gears);
314 memset(gears, 0, sizeof *gears);
Kristian Høgsberg43c28ee2009-01-26 23:42:46 -0500315 gears->d = display;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500316 gears->window = window_create(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500317 gears->widget = frame_create(gears->window, gears);
Kristian Høgsberg5f5324e2012-01-19 14:05:21 -0500318 window_set_transparent(gears->window, 1);
Kristian Høgsberg248c1b62011-01-21 18:03:15 -0500319 window_set_title(gears->window, "Wayland Gears");
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500320
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400321 gears->display = display_get_egl_display(gears->d);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500322 if (gears->display == NULL)
323 die("failed to create egl display\n");
324
Kristian Høgsbergf88ae452010-06-05 10:17:55 -0400325 eglBindAPI(EGL_OPENGL_API);
326
Kristian Høgsberg5f5324e2012-01-19 14:05:21 -0500327 gears->config = display_get_argb_egl_config(gears->d);
Benjamin Franzkecff904e2011-02-18 23:00:55 +0100328
329 gears->context = eglCreateContext(gears->display, gears->config,
330 EGL_NO_CONTEXT, NULL);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500331 if (gears->context == NULL)
332 die("failed to create context\n");
333
Kristian Høgsberga341fa02010-01-24 18:10:15 -0500334 if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context))
335 die("faile to make context current\n");
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500336
337 for (i = 0; i < 3; i++) {
338 gears->gear_list[i] = glGenLists(1);
339 glNewList(gears->gear_list[i], GL_COMPILE);
340 make_gear(&gear_templates[i]);
341 glEndList();
342 }
343
344 glEnable(GL_NORMALIZE);
345
346 glMatrixMode(GL_PROJECTION);
347 glLoadIdentity();
348 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0);
349 glMatrixMode(GL_MODELVIEW);
350
351 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
352 glEnable(GL_CULL_FACE);
353 glEnable(GL_LIGHTING);
354 glEnable(GL_LIGHT0);
355 glEnable(GL_DEPTH_TEST);
356 glClearColor(0, 0, 0, 0.92);
357
Kristian Høgsbergc8c37342010-06-25 11:19:22 -0400358 window_set_user_data(gears->window, gears);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500359 widget_set_resize_handler(gears->widget, resize_handler);
360 widget_set_redraw_handler(gears->widget, redraw_handler);
361 window_set_keyboard_focus_handler(gears->window,
362 keyboard_focus_handler);
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400363
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500364 window_schedule_resize(gears->window, width, height);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500365
366 return gears;
367}
368
369int main(int argc, char *argv[])
370{
Kristian Høgsberg43c28ee2009-01-26 23:42:46 -0500371 struct display *d;
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500372
Kristian Høgsberg9de79a92011-08-24 11:09:53 -0400373 d = display_create(&argc, &argv, NULL);
Yuval Fledele9f5e362010-11-22 21:34:19 +0200374 if (d == NULL) {
375 fprintf(stderr, "failed to create display: %m\n");
376 return -1;
377 }
Kristian Høgsberg00439612011-01-25 15:16:01 -0500378 gears_create(d);
Kristian Høgsberg7824d812010-06-08 14:59:44 -0400379 display_run(d);
Kristian Høgsberg0c4457f2008-12-07 19:59:11 -0500380
381 return 0;
382}