1 /*****************************************************************************/
2 /* XStarRoll - Letters fly to far, far, far away.                            */
3 /*                                                                           */
4 /* XStarRoll Copyright (c) 1998 Sakai Hiroaki.                               */
5 /* All Rights Reserved.                                                      */
6 /*                                                                           */
7 /* XStarRoll is a simple demonstration program for X11. Letters and pixmaps  */
8 /* fly to far, far, far away. You can fly optional letters and pixmaps, and  */
9 /* use XStarRoll as a background picture.                                    */
10 /*                                                                           */
11 /* XStarRoll is a free software. You may copy or distribute the original     */
12 /* XStarRoll freely. But, you may not modify or distribute the original      */
13 /* XStarRoll without permission of the author.                               */
14 /*****************************************************************************/
15 
16 /*****************************************************************************/
17 /* Include Header Files.                                                     */
18 /*****************************************************************************/
19 
20 #include<stdio.h>
21 #include<stdlib.h>
22 #include<X11/Xlib.h>
23 #include<X11/Intrinsic.h>
24 #include<X11/StringDefs.h>
25 #include<X11/keysym.h>
26 #include<X11/xpm.h>
27 #include<X11/Xaw/Label.h>
28 
29 /*****************************************************************************/
30 /* XStarRoll's version.                                                      */
31 /*****************************************************************************/
32 
33 #ifndef VERSION
34 #define VERSION "XStarRoll-unknown-version"
35 #endif
36 
37 /*****************************************************************************/
38 /* If you DEBUG, define below definition.                                    */
39 /*****************************************************************************/
40 
41 /*
42 #define DEBUG
43 */
44 
45 /*****************************************************************************/
46 /* Font.                                                                     */
47 /*****************************************************************************/
48 
49 #define DEFAULT_FONT_NAME "8x16"
50 
51 /*****************************************************************************/
52 /* Icon.                                                                     */
53 /*****************************************************************************/
54 
55 #include"xstarroll_icon.xpm"
56 #define XSTARROLL_ICON xstarroll_icon
57 
58 /*****************************************************************************/
59 /* Others.                                                                   */
60 /*****************************************************************************/
61 
62 #define OFF  0
63 #define ON   1
64 #define FILL 2
65 #define READ_FROM_STRING 0
66 #define READ_FROM_FILE   1
67 
68 /*****************************************************************************/
69 /* Default values.                                                           */
70 /*****************************************************************************/
71 
72 #define DEFAULT_CANVAS_WIDTH 640
73 #define DEFAULT_CANVAS_HEIGHT 480
74 #define DEFAULT_SOURCE_WIDTH 0
75 #define DEFAULT_WIDTH 40
76 #define DEFAULT_LENGTH_X 0
77 #define DEFAULT_LENGTH_Y 100
78 #define DEFAULT_SPACE 1
79 #define DEFAULT_SCROLL 1
80 #define DEFAULT_START 0
81 #define DEFAULT_WAIT 0
82 #define DEFAULT_TITLE_NAME "XStarRoll"
83 
84 /*****************************************************************************/
85 /* Default flags.                                                            */
86 /*****************************************************************************/
87 
88 #define DEFAULT_ROOT_FLAG 0
89 #define DEFAULT_DRAW_FLAG 1
90 #define DEFAULT_QUIT_FLAG 0
91 #define DEFAULT_BLUR_FLAG 1
92 
93 /*****************************************************************************/
94 /* Buffer.                                                                   */
95 /*****************************************************************************/
96 
97 #define TMP_BUFFER_SIZE 2048
98 static char tmp_buffer[TMP_BUFFER_SIZE];
99 
100 /*****************************************************************************/
101 /* Structures.                                                               */
102 /*****************************************************************************/
103 
104 typedef struct GCBuffer {
105   GC gc;
106   unsigned long int pixel;
107   struct GCBuffer * prev;
108   struct GCBuffer * next;
109 } GCBuffer;
110 
111 typedef struct GCBufferList {
112   GCBuffer * start;
113   GCBuffer * end;
114 } GCBufferList;
115 
116 typedef struct SourceData {
117   short int length;
118   GCBuffer * gc_buffer;
119   short int x;
120   short int y;
121   struct SourceData * prev;
122   struct SourceData * next;
123 } SourceData;
124 
125 typedef struct SourceDataList {
126   SourceData * start;
127   SourceData * end;
128 } SourceDataList;
129 
130 typedef struct FontDataList {
131   unsigned char pixel;
132   unsigned char length;
133   struct FontDataList * next;
134 } FontDataList;
135 
136 typedef struct FontData {
137   short int width;
138   FontDataList ** list_array;
139 } FontData;
140 
141 /*****************************************************************************/
142 /* Structure of XStarRoll.                                                   */
143 /*****************************************************************************/
144 
145 typedef struct XStarRoll {
146   XtAppContext app_context;
147   Display * display;
148   int screen, depth;
149   Colormap colormap;
150   Widget toplevel, canvas;
151   Window toplevel_window, root_window, canvas_window;
152   Pixmap canvas_pixmap, icon_pixmap;
153   Atom atom_1, atom_2;
154   unsigned long int foreground_color;
155   unsigned long int background_color;
156   unsigned long int foreground_pixel;
157   unsigned long int background_pixel;
158   GC gc_foreground, gc_background, gc_copy;
159   char * font_name;
160   Font font;
161   XFontStruct * font_struct;
162   char * title_name;
163   int canvas_width, canvas_height, source_width, width;
164   int icon_width, icon_height, font_height;
165   int root_flag, draw_flag, quit_flag, blur_flag;
166   int length_x, length_y, space, scroll, wait;
167   long int start;
168   GCBufferList * gc_buffer;
169   SourceDataList * source_data;
170   FontData * font_data;
171 } XStarRoll;
172 
173 /*****************************************************************************/
174 /* Help Message.                                                             */
175 /*****************************************************************************/
176 
177 char * help_string =
178 "\n\t" VERSION "\n"
179 "\tLetters fly to far, far, far away.\n"
180 "\n"
181 "\tDESCRIPTION\n"
182 "\n"
183 "    XStarRoll is a simple demonstration program for X11. Letters and pixmaps fly to far, far, far away. You can fly optional letters and pixmaps, and use XStarRoll as a background picture.\n"
184 "\n"
185 "\tSYNOPSIS\n"
186 "\n"
187 "\txstarroll [parameter1] [parameter2] ...\n"
188 "\n"
189 "    If a parameter is a pixmap filename, XStarRoll reads it and flies the pixmap, or, if the parameter is a text filename, XStarRoll reads it and flies letters in it, or else, xstarroll flies the parameter as it is.\n"
190 "    You can send letters to XStarRoll through the standard input.\n"
191 "\n"
192 "\tOPTIONS\n"
193 "\n"
194 "(X-ToolKit Options)    -display, -geometry, -name, -font, -fg and -bg are available.\n"
195 "--    End of options. XStarRoll ignores following options.\n"
196 "-    Read letters from the standard input.\n"
197 "-help, -h    Output this Message.\n"
198 "-root, -r    Draw the picture on the root window of the display.\n"
199 "-noroot, -nr    Open a new window and draw the picture on it. (Default)\n"
200 "-quit, -q    Draw the picture and exit.\n"
201 "-noquit, -nq    XStarRoll does not exit. (Default)\n"
202 "-blur, -b    Letters fly to the farther, become the more blurred. (Default)\n"
203 "-noblur, -nb    Letters do not become blurred.\n"
204 "-fill    Fill all dots entirely.\n"
205 "-source-width [x], -sw [x]    Specify the width of the source picture for a pixel.\n"
206 "-width [x], -w [x]    Specify the width of the source picture for a letter. Default value is 40.\n"
207 "-length-x [x], -lx [x]    Specify the length parameter of X-direction for drawing. Default value is same as the size of the source picture.\n"
208 "-length-y [x], -ly [x]    Specify the length parameter of Y-direction for drawing. Default value is 100.\n"
209 "-space [x], -sp [x]    Specify the space between lines. Default value is 1.\n"
210 "-scroll [x], -sc [x]    Specify the speed and direction of the scroll. Default value is 1.\n"
211 "-start [x], -st [x]    Specify the start point. Default value is 0.\n"
212 "-wait [x], -wt [x]    Specify the wait time for a micro second. Default value is 0.\n"
213 "\n"
214 "\tKEY OPERATIONS\n"
215 "\n"
216 "[Up], [Down], [Right], [Left]    Change the length parameters for drawing.\n"
217 "[a], [d]    Change the speed of the scroll.\n"
218 "[p], [n], [PageUp], [PageDown]    Scroll the picture.\n"
219 "[s]    Return to the start point.\n"
220 "[q]    Quit.\n"
221 "\n"
222 "\tEXAMPLES\n"
223 "\n"
224 "% ls -l | xstarroll\n"
225 "    - XStarRoll flies the output of ls.\n"
226 "% echo \"This is XStarRoll.\" | xstarroll\n"
227 "% xstarroll \"This is XStarRoll.\"\n"
228 "    - XStarRoll flies \"This is XStarRoll.\".\n"
229 "% echo \"is\" | xstarroll \"This\" - \"XStarRoll.\"\n"
230 "    - XStarRoll flies \"This\", \"is\" and \"XStarRoll.\".\n"
231 "% xstarroll sample.txt\n"
232 "    - XStarRoll flies letters in a file \"sample.txt\".\n"
233 "% xstarroll sample.xpm\n"
234 "    - XStarRoll flies a pixmap \"sample.xpm\".\n"
235 "% xstarroll \"This is XStarRoll.\" sample1.txt sample1.xpm sample2.txt sample2.xpm ...\n"
236 "    - XStarRoll flies \"This is XStarRoll.\", flies letters in a file sample1.txt, flies a pixmap sample1.xpm, flies letters in a file sample2.txt, flies a pixmap sample2.xpm ...\n"
237 "\n"
238 "    If the head of letters is a Tab code or \"#center\", XStarRoll flies letters at the center of the screen.\n"
239 "\n"
240 "\tSEE ALSO\n"
241 "\tX(1)\n"
242 "\n"
243 "\tAUTHOR\n"
244 "\tProgramed by Sakai Hiroaki.\n"
245 "\tE-Mail:sakai@miya.ee.kagu.sut.ac.jp\n"
246 "\thttp://wwwmiya.ee.kagu.sut.ac.jp/~sakai/myfreesoft.html\n"
247 "\n"
248 "\tCOPYRIGHT\n"
249 "\n"
250 "\tXStarRoll Copyright (c) 1998 Sakai Hiroaki.\n"
251 "\tAll Rights Reserved.\n"
252 "\n"
253 "    XStarRoll is a free software. You may copy or distribute the original XStarRoll freely. But, you may not modify or distribute the original XStarRoll without permission of the author.\n"
254 "\n";
255 
256 /*****************************************************************************/
257 /* Functions.                                                                */
258 /*****************************************************************************/
259 
260 /*****************************************************************************/
261 /* Operations of list structures.                                            */
262 /*****************************************************************************/
263 
264 /*****************************************************************************/
265 /* GCBuffer.                                                                 */
266 /*****************************************************************************/
267 
CreateGCBuffer(Display * display,Window window,unsigned long int pixel)268 GCBuffer * CreateGCBuffer(Display * display, Window window,
269 			  unsigned long int pixel)
270 {
271   GCBuffer * p;
272 
273   p = (GCBuffer *)malloc(sizeof(GCBuffer));
274   p->gc = XCreateGC(display, window, 0, NULL);
275   XSetForeground(display, p->gc, pixel);
276   XSetFillRule(display, p->gc, WindingRule);
277   XSetLineAttributes(display, p->gc, 0, LineSolid, CapNotLast ,JoinMiter);
278   p->pixel = pixel;
279   p->prev = (GCBuffer *)NULL;
280   p->next = (GCBuffer *)NULL;
281   return (p);
282 }
283 
FreeGCBuffer(Display * display,GCBuffer * p)284 void FreeGCBuffer(Display * display, GCBuffer * p)
285 {
286   XFreeGC(display, p->gc);
287   free(p);
288 }
289 
InitializeGCBufferList()290 GCBufferList * InitializeGCBufferList()
291 {
292   GCBufferList * p;
293 
294   p = (GCBufferList *)malloc(sizeof(GCBufferList));
295   p->start = (GCBuffer *)NULL;
296   p->end = (GCBuffer *)NULL;
297   return (p);
298 }
299 
FreeGCBufferList(Display * display,GCBufferList * p)300 void FreeGCBufferList(Display * display, GCBufferList * p)
301 {
302   GCBuffer * q;
303 
304   while (p->start != (GCBuffer *)NULL) {
305     q = p->start->next;
306     FreeGCBuffer(display, p->start);
307     p->start = q;
308   }
309   free(p);
310 }
311 
GetGCBufferFromTop(GCBufferList * p)312 GCBuffer * GetGCBufferFromTop(GCBufferList * p)
313 {
314   return (p->start);
315 }
316 
GetGCBufferFromBottom(GCBufferList * p)317 GCBuffer * GetGCBufferFromBottom(GCBufferList * p)
318 {
319   return (p->end);
320 }
321 
AddGCBufferToTop(GCBufferList * p,GCBuffer * d)322 GCBuffer * AddGCBufferToTop(GCBufferList * p, GCBuffer * d)
323 {
324   if (d == (GCBuffer *)NULL) return (GCBuffer *)NULL;
325   if (p->start == (GCBuffer *)NULL) {
326     d->prev = (GCBuffer *)NULL;
327     d->next = (GCBuffer *)NULL;
328     p->start = d;
329     p->end = d;
330   } else {
331     d->prev = (GCBuffer *)NULL;
332     d->next = p->start;
333     p->start->prev = d;
334     p->start = d;
335   }
336   return (p->start);
337 }
338 
AddGCBufferToBottom(GCBufferList * p,GCBuffer * d)339 GCBuffer * AddGCBufferToBottom(GCBufferList * p, GCBuffer * d)
340 {
341   if (d == (GCBuffer *)NULL) return (GCBuffer *)NULL;
342   if (p->start == (GCBuffer *)NULL) {
343     d->prev = (GCBuffer *)NULL;
344     d->next = (GCBuffer *)NULL;
345     p->start = d;
346     p->end = d;
347   } else {
348     d->next = (GCBuffer *)NULL;
349     d->prev = p->end;
350     p->end->next = d;
351     p->end = d;
352   }
353   return (p->end);
354 }
355 
DeleteGCBufferFromTop(GCBufferList * p)356 GCBuffer * DeleteGCBufferFromTop(GCBufferList * p)
357 {
358   GCBuffer * q;
359 
360   if (p->start == (GCBuffer *)NULL) return ((GCBuffer *)NULL);
361   q = p->start;
362   p->start = p->start->next;
363   if (p->start == (GCBuffer *)NULL) p->end = (GCBuffer *)NULL;
364   else p->start->prev = (GCBuffer *)NULL;
365   q->prev = (GCBuffer *)NULL;
366   q->next = (GCBuffer *)NULL;
367   return (q);
368 }
369 
DeleteGCBufferFromBottom(GCBufferList * p)370 GCBuffer * DeleteGCBufferFromBottom(GCBufferList * p)
371 {
372   GCBuffer * q;
373 
374   if (p->start == (GCBuffer *)NULL) return ((GCBuffer *)NULL);
375   q = p->end;
376   p->end = p->end->prev;
377   if (p->end == (GCBuffer *)NULL) p->start = (GCBuffer *)NULL;
378   else p->end->next = (GCBuffer *)NULL;
379   q->prev = (GCBuffer *)NULL;
380   q->next = (GCBuffer *)NULL;
381   return (q);
382 }
383 
DeleteGCBuffer(GCBufferList * p,GCBuffer * d)384 GCBuffer * DeleteGCBuffer(GCBufferList * p, GCBuffer * d)
385 {
386   if (p->start == (GCBuffer *)NULL) return ((GCBuffer *)NULL);
387   else if (d == (GCBuffer *)NULL) return ((GCBuffer *)NULL);
388   else if (d->prev == (GCBuffer *)NULL)
389     return (DeleteGCBufferFromTop(p));
390   else if (d->next == (GCBuffer *)NULL)
391     return (DeleteGCBufferFromBottom(p));
392   else {
393     d->prev->next = d->next;
394     d->next->prev = d->prev;
395     d->prev = (GCBuffer *)NULL;
396     d->next = (GCBuffer *)NULL;
397     return (d);
398   }
399 }
400 
MoveGCBufferFromBottomToTop(GCBufferList * p)401 GCBuffer * MoveGCBufferFromBottomToTop(GCBufferList * p)
402 {
403   GCBuffer * q;
404 
405   q = DeleteGCBufferFromBottom(p);
406   return (AddGCBufferToTop(p, q));
407 }
408 
MoveGCBufferFromTopToBottom(GCBufferList * p)409 GCBuffer * MoveGCBufferFromTopToBottom(GCBufferList * p)
410 {
411   GCBuffer * q;
412 
413   q = DeleteGCBufferFromTop(p);
414   return (AddGCBufferToBottom(p, q));
415 }
416 
MoveGCBufferToTop(GCBufferList * p,GCBuffer * d)417 GCBuffer * MoveGCBufferToTop(GCBufferList * p, GCBuffer * d)
418 {
419   GCBuffer * q;
420 
421   q = DeleteGCBuffer(p, d);
422   return (AddGCBufferToTop(p, q));
423 }
424 
MoveGCBufferToBottom(GCBufferList * p,GCBuffer * d)425 GCBuffer * MoveGCBufferToBottom(GCBufferList * p, GCBuffer * d)
426 {
427   GCBuffer * q;
428 
429   q = DeleteGCBuffer(p, d);
430   return (AddGCBufferToBottom(p, q));
431 }
432 
433 /*****************************************************************************/
434 /* SourceData.                                                               */
435 /*****************************************************************************/
436 
CreateSourceData(int length,GCBuffer * gc_buffer,int x,int y)437 SourceData * CreateSourceData(int length, GCBuffer * gc_buffer, int x, int y)
438 {
439   SourceData * p;
440 
441   p = (SourceData *)malloc(sizeof(SourceData));
442   p->length = (short int)length;
443   p->gc_buffer = gc_buffer;
444   p->x = (short int)x;
445   p->y = (short int)y;
446   p->prev = (SourceData *)NULL;
447   p->next = (SourceData *)NULL;
448   return (p);
449 }
450 
FreeSourceData(SourceData * p)451 void FreeSourceData(SourceData * p)
452 {
453   free(p);
454 }
455 
InitializeSourceDataList()456 SourceDataList * InitializeSourceDataList()
457 {
458   SourceDataList * p;
459 
460   p = (SourceDataList *)malloc(sizeof(SourceDataList));
461   p->start = (SourceData *)NULL;
462   p->end = (SourceData *)NULL;
463   return (p);
464 }
465 
FreeSourceDataList(SourceDataList * p)466 void FreeSourceDataList(SourceDataList * p)
467 {
468   SourceData * q;
469 
470   while (p->start != (SourceData *)NULL) {
471     q = p->start->next;
472     FreeSourceData(p->start);
473     p->start = q;
474   }
475   free(p);
476 }
477 
GetSourceDataFromTop(SourceDataList * p)478 SourceData * GetSourceDataFromTop(SourceDataList * p)
479 {
480   return (p->start);
481 }
482 
GetSourceDataFromBottom(SourceDataList * p)483 SourceData * GetSourceDataFromBottom(SourceDataList * p)
484 {
485   return (p->end);
486 }
487 
AddSourceDataToTop(SourceDataList * p,SourceData * d)488 SourceData * AddSourceDataToTop(SourceDataList * p, SourceData * d)
489 {
490   if (d == (SourceData *)NULL) return (SourceData *)NULL;
491   if (p->start == (SourceData *)NULL) {
492     d->prev = (SourceData *)NULL;
493     d->next = (SourceData *)NULL;
494     p->start = d;
495     p->end = d;
496   } else {
497     d->prev = (SourceData *)NULL;
498     d->next = p->start;
499     p->start->prev = d;
500     p->start = d;
501   }
502   return (p->start);
503 }
504 
AddSourceDataToBottom(SourceDataList * p,SourceData * d)505 SourceData * AddSourceDataToBottom(SourceDataList * p, SourceData * d)
506 {
507   if (d == (SourceData *)NULL) return (SourceData *)NULL;
508   if (p->start == (SourceData *)NULL) {
509     d->prev = (SourceData *)NULL;
510     d->next = (SourceData *)NULL;
511     p->start = d;
512     p->end = d;
513   } else {
514     d->next = (SourceData *)NULL;
515     d->prev = p->end;
516     p->end->next = d;
517     p->end = d;
518   }
519   return (p->end);
520 }
521 
DeleteSourceDataFromTop(SourceDataList * p)522 SourceData * DeleteSourceDataFromTop(SourceDataList * p)
523 {
524   SourceData * q;
525 
526   if (p->start == (SourceData *)NULL) return ((SourceData *)NULL);
527   q = p->start;
528   p->start = p->start->next;
529   if (p->start == (SourceData *)NULL) p->end = (SourceData *)NULL;
530   else p->start->prev = (SourceData *)NULL;
531   q->prev = (SourceData *)NULL;
532   q->next = (SourceData *)NULL;
533   return (q);
534 }
535 
DeleteSourceDataFromBottom(SourceDataList * p)536 SourceData * DeleteSourceDataFromBottom(SourceDataList * p)
537 {
538   SourceData * q;
539 
540   if (p->start == (SourceData *)NULL) return ((SourceData *)NULL);
541   q = p->end;
542   p->end = p->end->prev;
543   if (p->end == (SourceData *)NULL) p->start = (SourceData *)NULL;
544   else p->end->next = (SourceData *)NULL;
545   q->prev = (SourceData *)NULL;
546   q->next = (SourceData *)NULL;
547   return (q);
548 }
549 
DeleteSourceData(SourceDataList * p,SourceData * d)550 SourceData * DeleteSourceData(SourceDataList * p, SourceData * d)
551 {
552   if (p->start == (SourceData *)NULL) return ((SourceData *)NULL);
553   else if (d == (SourceData *)NULL) return ((SourceData *)NULL);
554   else if (d->prev == (SourceData *)NULL)
555     return (DeleteSourceDataFromTop(p));
556   else if (d->next == (SourceData *)NULL)
557     return (DeleteSourceDataFromBottom(p));
558   else {
559     d->prev->next = d->next;
560     d->next->prev = d->prev;
561     d->prev = (SourceData *)NULL;
562     d->next = (SourceData *)NULL;
563     return (d);
564   }
565 }
566 
MoveSourceDataFromBottomToTop(SourceDataList * p)567 SourceData * MoveSourceDataFromBottomToTop(SourceDataList * p)
568 {
569   SourceData * q;
570 
571   q = DeleteSourceDataFromBottom(p);
572   return (AddSourceDataToTop(p, q));
573 }
574 
MoveSourceDataFromTopToBottom(SourceDataList * p)575 SourceData * MoveSourceDataFromTopToBottom(SourceDataList * p)
576 {
577   SourceData * q;
578 
579   q = DeleteSourceDataFromTop(p);
580   return (AddSourceDataToBottom(p, q));
581 }
582 
MoveSourceDataToTop(SourceDataList * p,SourceData * d)583 SourceData * MoveSourceDataToTop(SourceDataList * p, SourceData * d)
584 {
585   SourceData * q;
586 
587   q = DeleteSourceData(p, d);
588   return (AddSourceDataToTop(p, q));
589 }
590 
MoveSourceDataToBottom(SourceDataList * p,SourceData * d)591 SourceData * MoveSourceDataToBottom(SourceDataList * p, SourceData * d)
592 {
593   SourceData * q;
594 
595   q = DeleteSourceData(p, d);
596   return (AddSourceDataToBottom(p, q));
597 }
598 
599 /*****************************************************************************/
600 /* Graphic.                                                                  */
601 /*****************************************************************************/
602 
MakePixmapFromFile(XStarRoll * p,char * filename,int * w,int * h)603 Pixmap MakePixmapFromFile(XStarRoll * p, char * filename, int * w, int * h)
604 {
605   XpmAttributes attr;
606   Pixmap pix, mask;
607 
608   attr.colormap = p->colormap;
609   attr.closeness = 40000;
610   attr.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
611   XpmReadFileToPixmap(p->display, p->toplevel_window, filename,
612 		      &pix, &mask, &attr);
613   *w = attr.width;
614   *h = attr.height;
615   return (pix);
616 }
617 
MakePixmapFromData(XStarRoll * p,char ** string,int * w,int * h)618 Pixmap MakePixmapFromData(XStarRoll * p, char ** string, int * w, int * h)
619 {
620   XpmAttributes attr;
621   Pixmap pix, mask;
622 
623   attr.colormap = p->colormap;
624   attr.closeness = 40000;
625   attr.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
626   XpmCreatePixmapFromData(p->display, p->toplevel_window, string,
627 			  &pix, &mask, &attr);
628   *w = attr.width;
629   *h = attr.height;
630   return (pix);
631 }
632 
633 /*****************************************************************************/
634 /* Functions for XStarRoll.                                                  */
635 /*****************************************************************************/
636 
SetDefaultValues(XStarRoll * p)637 void SetDefaultValues(XStarRoll * p)
638 {
639   p->canvas_width = DEFAULT_CANVAS_WIDTH;
640   p->canvas_height = DEFAULT_CANVAS_HEIGHT;
641   p->source_width = DEFAULT_SOURCE_WIDTH;
642   p->width = DEFAULT_WIDTH;
643   p->length_x = DEFAULT_LENGTH_X;
644   p->length_y = DEFAULT_LENGTH_Y;
645   p->space   = DEFAULT_SPACE;
646   p->scroll = DEFAULT_SCROLL;
647   p->start = DEFAULT_START;
648   p->wait = DEFAULT_WAIT;
649   p->root_flag = DEFAULT_ROOT_FLAG;
650   p->draw_flag = DEFAULT_DRAW_FLAG;
651   p->quit_flag = DEFAULT_QUIT_FLAG;
652   p->blur_flag = DEFAULT_BLUR_FLAG;
653   p->font_name = DEFAULT_FONT_NAME;
654   p->title_name = DEFAULT_TITLE_NAME;
655 }
656 
ConnectDisplay(XStarRoll * p,int * argc,char ** argv)657 void ConnectDisplay(XStarRoll * p, int * argc, char ** argv)
658 {
659   int n;
660   Arg args[10];
661 
662   n = 0;
663   XtSetArg(args[n], XtNwidth,  p->canvas_width); n++;
664   XtSetArg(args[n], XtNheight, p->canvas_height); n++;
665   p->toplevel = XtAppInitialize(&(p->app_context), "XStarRoll",
666 				NULL, 0, argc, argv, NULL, args, n);
667 }
668 
Help()669 void Help()
670 {
671   printf("%s", help_string);
672   exit (0);
673 }
674 
DeleteParameter(int * c,char ** v,int i)675 void DeleteParameter(int * c, char ** v, int i)
676 {
677   (*c)--;
678   for (; i < (*c); i++)
679     v[i] = v[i + 1];
680 }
681 
SetFlagOn(int * c,char ** v,int i)682 int SetFlagOn(int * c, char ** v, int i)
683 {
684   DeleteParameter(c, v, i);
685   return (ON);
686 }
687 
SetFlagOff(int * c,char ** v,int i)688 int SetFlagOff(int * c, char ** v, int i)
689 {
690   DeleteParameter(c, v, i);
691   return (OFF);
692 }
693 
SetFlag(int * c,char ** v,int i,int f)694 int SetFlag(int * c, char ** v, int i, int f)
695 {
696   DeleteParameter(c, v, i);
697   return (f);
698 }
699 
GetIntValueFromParameter(int * c,char ** v,int i,int value)700 int GetIntValueFromParameter(int * c, char ** v, int i, int value)
701 {
702   int a;
703 
704   DeleteParameter(c, v, i);
705   if (i < *c) {
706     a = atoi(v[i]);
707     DeleteParameter(c, v, i);
708     return (a);
709   }
710   return (value);
711 }
712 
GetStringValueFromParameter(int * c,char ** v,int i,char * value)713 char * GetStringValueFromParameter(int * c, char ** v, int i, char * value)
714 {
715   char * a;
716 
717   DeleteParameter(c, v, i);
718   if (i < *c) {
719     a = v[i];
720     DeleteParameter(c, v, i);
721     return (a);
722   }
723   return (value);
724 }
725 
ReadParameters(XStarRoll * p,int * c,char ** v)726 void ReadParameters(XStarRoll * p, int * c, char ** v)
727 {
728   int i = 1;
729 
730   while (i < *c) {
731     if (!strcmp(v[i], "--")) while (i < *c) DeleteParameter(c, v, i);
732     else if ( (!strcmp(v[i], "-help")) || (!strcmp(v[i], "-h")) ) Help();
733     else if ( (!strcmp(v[i], "-root")) || (!strcmp(v[i], "-r")) )
734       p->root_flag = SetFlagOn(c, v, i);
735     else if ( (!strcmp(v[i], "-noroot")) || (!strcmp(v[i], "-nr")) )
736       p->root_flag = SetFlagOff(c, v, i);
737     else if ( (!strcmp(v[i], "-quit")) || (!strcmp(v[i], "-q")) )
738       p->quit_flag = SetFlagOn(c, v, i);
739     else if ( (!strcmp(v[i], "-noquit")) || (!strcmp(v[i], "-nq")) )
740       p->quit_flag = SetFlagOff(c, v, i);
741     else if ( (!strcmp(v[i], "-blur")) || (!strcmp(v[i], "-b")) )
742       p->blur_flag = SetFlagOn(c, v, i);
743     else if ( (!strcmp(v[i], "-noblur")) || (!strcmp(v[i], "-nb")) )
744       p->blur_flag = SetFlagOff(c, v, i);
745     else if (!strcmp(v[i], "-fill"))
746       p->blur_flag = SetFlag(c, v, i, 2);
747     else if ( (!strcmp(v[i], "-source-width")) || (!strcmp(v[i], "-sw")) )
748       p->source_width = GetIntValueFromParameter(c, v, i, p->source_width);
749     else if ( (!strcmp(v[i], "-width")) || (!strcmp(v[i], "-w")) )
750       p->width = GetIntValueFromParameter(c, v, i, p->width);
751     else if ( (!strcmp(v[i], "-length-x")) || (!strcmp(v[i], "-lx")) )
752       p->length_x = GetIntValueFromParameter(c, v, i, p->length_x);
753     else if ( (!strcmp(v[i], "-length-y")) || (!strcmp(v[i], "-ly")) )
754       p->length_y = GetIntValueFromParameter(c, v, i, p->length_y);
755     else if ( (!strcmp(v[i], "-space")) || (!strcmp(v[i], "-sp")) )
756       p->space = GetIntValueFromParameter(c, v, i, p->space);
757     else if ( (!strcmp(v[i], "-scroll")) || (!strcmp(v[i], "-sc")) )
758       p->scroll = GetIntValueFromParameter(c, v, i, p->scroll);
759     else if ( (!strcmp(v[i], "-start")) || (!strcmp(v[i], "-st")) )
760       p->start = (long int)GetIntValueFromParameter(c, v, i, (int)(p->start));
761     else if ( (!strcmp(v[i], "-wait")) || (!strcmp(v[i], "-wt")) )
762       p->wait = GetIntValueFromParameter(c, v, i, p->wait);
763     else if ( (!strcmp(v[i], "-font")) || (!strcmp(v[i], "-fn")) )
764       p->font_name = GetStringValueFromParameter(c, v, i, p->font_name);
765     else if ( (!strcmp(v[i], "-name")) || (!strcmp(v[i], "-title")) )
766       p->title_name = GetStringValueFromParameter(c, v, i, p->title_name);
767     else i++;
768   }
769 }
770 
InitializeParameters(XStarRoll * p,int * argc,char ** argv)771 void InitializeParameters(XStarRoll * p, int * argc, char ** argv)
772 {
773   SetDefaultValues(p);
774   ReadParameters(p, argc, argv);
775   ConnectDisplay(p, argc, argv);
776 }
777 
InitializeDisplay(XStarRoll * p)778 void InitializeDisplay(XStarRoll * p)
779 {
780   int n;
781   Arg args[10];
782 
783   p->display = XtDisplay(p->toplevel);
784   p->screen = DefaultScreen(p->display);
785   p->colormap = XDefaultColormap(p->display, p->screen);
786   p->root_window = RootWindow(p->display, p->screen);
787   p->depth = DefaultDepth(p->display, p->screen);
788   p->canvas = XtCreateManagedWidget("", labelWidgetClass, p->toplevel,
789 				    NULL, 0);
790   n = 0;
791   XtSetArg(args[n], XtNforeground, &(p->foreground_color)); n++;
792   XtSetArg(args[n], XtNbackground, &(p->background_color)); n++;
793   XtGetValues(p->canvas, args, n);
794   if (p->root_flag == ON) {
795     p->toplevel_window = p->root_window;
796     p->canvas_window = p->root_window;
797     p->canvas_width = DisplayWidth(p->display, p->screen);
798     p->canvas_height = DisplayHeight(p->display, p->screen);
799   } else {
800     XtRealizeWidget(p->toplevel);
801     p->toplevel_window = XtWindow(p->toplevel);
802     p->canvas_window = XtWindow(p->canvas);
803     n = 0;
804     XtSetArg(args[n], XtNwidth,  &(p->canvas_width)); n++;
805     XtSetArg(args[n], XtNheight, &(p->canvas_height)); n++;
806     XtGetValues(p->toplevel, args, n);
807   }
808   p->canvas_pixmap = XCreatePixmap(p->display, p->toplevel_window,
809 				   p->canvas_width, p->canvas_height,
810 				   p->depth);
811   p->font = XLoadFont(p->display, p->font_name);
812   p->font_struct = XQueryFont(p->display, p->font);
813   if (p->source_width == 0)
814     p->source_width = p->width *
815     ((p->font_struct->max_bounds.width +
816       p->font_struct->min_bounds.width) / 2);
817   if (p->length_x < 1) p->length_x = p->source_width;
818   XFlush(p->display);
819 }
820 
InitializeGC(XStarRoll * p)821 void InitializeGC(XStarRoll * p)
822 {
823   p->gc_foreground = XCreateGC(p->display, p->toplevel_window, 0, NULL);
824   p->gc_background = XCreateGC(p->display, p->toplevel_window, 0, NULL);
825   p->gc_copy = XCreateGC(p->display, p->toplevel_window, 0, NULL);
826   XSetForeground(p->display, p->gc_foreground, p->foreground_color);
827   XSetBackground(p->display, p->gc_foreground, p->background_color);
828   XSetForeground(p->display, p->gc_background, p->background_color);
829   XSetBackground(p->display, p->gc_background, p->background_color);
830   XSetFont(p->display, p->gc_foreground, p->font);
831   XSetFunction(p->display, p->gc_copy, GXcopy);
832   XSetFillRule(p->display, p->gc_foreground, WindingRule);
833   XSetFillRule(p->display, p->gc_background, WindingRule);
834   XSetLineAttributes(p->display, p->gc_foreground, 0,
835 		     LineSolid, CapNotLast ,JoinMiter);
836 }
837 
GetCharFromPointer(void ** pp,int flag)838 int GetCharFromPointer(void ** pp, int flag)
839 {
840   int c;
841   char ** cpp;
842   FILE ** fpp;
843 
844   if (flag == READ_FROM_STRING) {
845     cpp = (char **)pp;
846     c = **cpp;
847     if (c == '\0') c = EOF;
848     else (*cpp)++;
849   } else if (flag == READ_FROM_FILE) {
850     fpp = (FILE **)pp;
851     c = fgetc(*fpp);
852   }
853   return (c);
854 }
855 
SearchGCBufferFromPixel(XStarRoll * p,unsigned long int pixel)856 GCBuffer * SearchGCBufferFromPixel(XStarRoll * p, unsigned long int pixel)
857 {
858   GCBuffer * gp;
859 
860   gp = p->gc_buffer->start;
861   while (gp != (GCBuffer *)NULL)
862     if (gp->pixel == pixel) return (gp);
863     else gp = gp->next;
864   return ((GCBuffer *)NULL);
865 }
866 
GetGCBufferFromPixel(XStarRoll * p,unsigned long int pixel)867 GCBuffer * GetGCBufferFromPixel(XStarRoll * p, unsigned long int pixel)
868 {
869   GCBuffer * gp;
870 
871   gp = SearchGCBufferFromPixel(p, pixel);
872   if (gp == (GCBuffer *)NULL) {
873     gp = CreateGCBuffer(p->display, p->toplevel_window, pixel);
874     gp = AddGCBufferToTop(p->gc_buffer, gp);
875   } else
876     gp = MoveGCBufferToTop(p->gc_buffer, gp);
877   return (gp);
878 }
879 
MakeSourceDataFromPixmap(XStarRoll * p,Pixmap pixmap,int w,int h)880 void MakeSourceDataFromPixmap(XStarRoll * p, Pixmap pixmap, int w, int h)
881 {
882   XImage * image;
883   SourceData * sp;
884   GCBuffer * gp;
885   int x, y;
886   unsigned long int pixel;
887 
888   image = XGetImage(p->display, pixmap, 0, 0, w, h, AllPlanes, XYPixmap);
889   for (y = 0; y < h; y++) {
890     for (x = 0; x < w; x++) {
891       pixel = XGetPixel(image, x, y);
892       if ( (x == 0) || (pixel != sp->gc_buffer->pixel) ) {
893 	gp = GetGCBufferFromPixel(p, pixel);
894 	sp = CreateSourceData(1, gp, 1, 0);
895 	sp = AddSourceDataToBottom(p->source_data, sp);
896       } else {
897 	(sp->length)++;
898 	(sp->x)++;
899       }
900     }
901     sp->x -= w;
902     (sp->y)++;
903   }
904   XDestroyImage(image);
905 }
906 
MakeSourceDataFromFontData(XStarRoll * p,char * str,int n,int f)907 void MakeSourceDataFromFontData(XStarRoll * p, char * str, int n, int f)
908 {
909   SourceData * sp;
910   GCBuffer * fore_gp;
911   GCBuffer * back_gp;
912   GCBuffer * gp;
913   FontDataList * fp;
914   int i, j, off, len;
915   unsigned char * string;
916   unsigned char pixel;
917 
918   string = (unsigned char *)str;
919   fore_gp = GetGCBufferFromPixel(p, p->foreground_pixel);
920   back_gp = GetGCBufferFromPixel(p, p->background_pixel);
921 
922   if (f == ON) {
923     off = (p->source_width - XTextWidth(p->font_struct, str, n)) / 2;
924     sp = CreateSourceData(0, back_gp, off, 0);
925     sp = AddSourceDataToBottom(p->source_data, sp);
926   }
927 
928   if (n == 0) {
929     sp = CreateSourceData(0, back_gp, 0, p->font_height);
930     sp = AddSourceDataToBottom(p->source_data, sp);
931   } else {
932     for (i = 0; i < p->font_height; i++) {
933       len = 0;
934       sp = (SourceData *)NULL;
935       for (j = 0; j < n; j++) {
936 	fp = p->font_data[(int)(string[j])].list_array[i];
937 	if ( (sp != (SourceData *)NULL) && (fp->pixel == pixel) ) {
938 	  sp->x += fp->length;
939 	  sp->length += fp->length;
940 	  len += fp->length;
941 	  fp = fp->next;
942 	}
943 	while (fp != (FontDataList *)NULL) {
944 	  pixel = fp->pixel;
945 	  if (pixel == ON) gp = fore_gp;
946 	  else gp = back_gp;
947 	  sp = CreateSourceData((int)(fp->length), gp, (int)(fp->length), 0);
948 	  sp = AddSourceDataToBottom(p->source_data, sp);
949 	  len += fp->length;
950 	  fp = fp->next;
951 	}
952       }
953       sp = CreateSourceData(0, back_gp, - len, 1);
954       sp = AddSourceDataToBottom(p->source_data, sp);
955     }
956   }
957 
958   if (f == ON) {
959     sp = CreateSourceData(0, back_gp, - off, p->space);
960     sp = AddSourceDataToBottom(p->source_data, sp);
961   } else if (p->space != 0) {
962     sp = CreateSourceData(0, back_gp, 0, p->space);
963     sp = AddSourceDataToBottom(p->source_data, sp);
964   }
965 }
966 
MakeFontData(XStarRoll * p,int c)967 void MakeFontData(XStarRoll * p, int c)
968 {
969   int x, y, w, h;
970   char string[10];
971   Pixmap pixmap;
972   XImage * image;
973   unsigned char pixel;
974   FontDataList * fp;
975 
976   string[0] = (char)c;
977   string[1] = '\0';
978   p->font_data[c].width = w = XTextWidth(p->font_struct, string, 1);
979   h = p->font_height;
980   p->font_data[c].list_array =
981     (FontDataList **)malloc(sizeof(FontDataList *) * h);
982   pixmap = XCreatePixmap(p->display, p->toplevel_window, w, h, p->depth);
983   XFillRectangle(p->display, pixmap, p->gc_background, 0, 0, w, h);
984   XDrawString(p->display, pixmap, p->gc_foreground, 0, p->font_struct->ascent,
985 	      string, 1);
986   image = XGetImage(p->display, pixmap, 0, 0, w, h, AllPlanes, XYPixmap);
987   for (y = 0; y < h; y++) {
988     for (x = 0; x < w; x++) {
989       if (XGetPixel(image, x, y) == p->background_pixel) pixel = OFF;
990       else pixel = ON;
991       if ( (x == 0) || (pixel != fp->pixel) ) {
992 	if (x == 0)
993 	  fp = p->font_data[c].list_array[y] =
994 	  (FontDataList *)malloc(sizeof(FontDataList));
995 	else {
996 	  fp->next = (FontDataList *)malloc(sizeof(FontDataList));
997 	  fp = fp->next;
998 	}
999 	fp->pixel = pixel;
1000 	fp->length = 1;
1001 	fp->next = (FontDataList *)NULL;
1002       } else (fp->length)++;
1003     }
1004   }
1005   XDestroyImage(image);
1006   XFreePixmap(p->display, pixmap);
1007 }
1008 
WriteLetters(XStarRoll * p,void * pointer,int flag)1009 void WriteLetters(XStarRoll * p, void * pointer, int flag)
1010 {
1011   int i, c;
1012   int center_flag = OFF;
1013 
1014   tmp_buffer[i = 0] = '\0';
1015   while ((c = GetCharFromPointer(&pointer, flag)) != EOF) {
1016     if (c == '\n') {
1017       MakeSourceDataFromFontData(p, tmp_buffer, i, center_flag);
1018       tmp_buffer[i = 0] = '\0';
1019       center_flag = OFF;
1020     }
1021     else if ( (c == '\t') && (i == 0) ) center_flag = ON;
1022     else if ( (c == '\b') && (i > 0) ) tmp_buffer[--i] = '\0';
1023     else if (c == 0x1B)
1024       while ( (((c = GetCharFromPointer(&pointer, flag)) < 'A') || (c > 'Z'))
1025 	     && ((c < 'a') || (c > 'z')) && (c != EOF) );
1026     else if (c < ' ');
1027     else {
1028       if (p->font_data[c].list_array == (FontDataList **)NULL)
1029 	MakeFontData(p, c);
1030       if (i < TMP_BUFFER_SIZE - 1) {
1031 	tmp_buffer[i++] = (char)c;
1032 	tmp_buffer[i] = '\0';
1033       }
1034       if (!strcmp(tmp_buffer, "#center")) {
1035 	tmp_buffer[i = 0] = '\0';
1036 	center_flag = ON;
1037       } else if (XTextWidth(p->font_struct, tmp_buffer, i) > p->source_width) {
1038 	tmp_buffer[--i] = '\0';
1039 	MakeSourceDataFromFontData(p, tmp_buffer, i, center_flag);
1040 	tmp_buffer[i = 0] = (char)c;
1041 	tmp_buffer[++i] = '\0';
1042       }
1043     }
1044   }
1045   if (i > 0) MakeSourceDataFromFontData(p, tmp_buffer, i, center_flag);
1046 }
1047 
DrawPixmap(XStarRoll * p,char * filename)1048 void DrawPixmap(XStarRoll * p, char * filename)
1049 {
1050   int w, h, off;
1051   Pixmap pixmap;
1052   SourceData * sp;
1053   GCBuffer * back_gp;
1054 
1055   pixmap = MakePixmapFromFile(p, filename, &w, &h);
1056   off = (p->source_width - w) / 2;
1057   back_gp = GetGCBufferFromPixel(p, p->background_pixel);
1058   sp = CreateSourceData(0, back_gp, (short int)off, 0);
1059   sp = AddSourceDataToBottom(p->source_data, sp);
1060   MakeSourceDataFromPixmap(p, pixmap, w, h);
1061   sp = CreateSourceData(0, back_gp, (short int)(- off), 0);
1062   sp = AddSourceDataToBottom(p->source_data, sp);
1063   XFreePixmap(p->display, pixmap);
1064 }
1065 
OutputMessage(XStarRoll * p,char * string)1066 void OutputMessage(XStarRoll * p, char * string)
1067 {
1068   static y = 0;
1069 
1070   y += p->font_struct->ascent + p->font_struct->descent + p->space;
1071   XDrawString(p->display, p->canvas_pixmap, p->gc_foreground,
1072 	      p->font_struct->max_bounds.width, y, string, strlen(string));
1073   XCopyArea(p->display, p->canvas_pixmap, p->canvas_window, p->gc_copy,
1074 	    0, 0, p->canvas_width, p->canvas_height, 0, 0);
1075   XFlush(p->display);
1076 }
1077 
FreeFontData(XStarRoll * p)1078 void FreeFontData(XStarRoll * p)
1079 {
1080   int i, j;
1081   FontDataList * fp;
1082   FontDataList * fp_next;
1083 
1084   for (i = 0; i < 256; i++) {
1085     if (p->font_data[i].list_array != (FontDataList **)NULL) {
1086       for (j = 0; j < p->font_height; j++) {
1087 	fp = p->font_data[i].list_array[j];
1088 	while (fp != (FontDataList *)NULL) {
1089 	  fp_next = fp->next;
1090 	  free(fp);
1091 	  fp = fp_next;
1092 	}
1093       }
1094       free(p->font_data[i].list_array);
1095     }
1096   }
1097   free(p->font_data);
1098 }
1099 
GetBlackAndWhitePixel(XStarRoll * p)1100 void GetBlackAndWhitePixel(XStarRoll * p)
1101 {
1102   Pixmap pix;
1103   XImage * image;
1104 
1105   pix = XCreatePixmap(p->display, p->toplevel_window, 2, 1, p->depth);
1106   XDrawPoint(p->display, pix, p->gc_foreground, 0, 0);
1107   XDrawPoint(p->display, pix, p->gc_background, 1, 0);
1108   image = XGetImage(p->display, pix, 0, 0, 2, 1, AllPlanes, XYPixmap);
1109   p->foreground_pixel = XGetPixel(image, 0, 0);
1110   p->background_pixel = XGetPixel(image, 1, 0);
1111   XDestroyImage(image);
1112   XFreePixmap(p->display, pix);
1113 }
1114 
InitializeStarRoll(XStarRoll * p,int * argc,char ** argv)1115 void InitializeStarRoll(XStarRoll * p, int * argc, char ** argv)
1116 {
1117   FILE * fp;
1118   int i;
1119 
1120   p->gc_buffer = InitializeGCBufferList();
1121   p->source_data = InitializeSourceDataList();
1122   p->font_data = (FontData *)malloc(sizeof(FontData) * 256);
1123   for (i = 0; i < 256; i++) p->font_data[i].list_array = (FontDataList **)NULL;
1124   p->font_height = p->font_struct->ascent + p->font_struct->descent;
1125 
1126   GetBlackAndWhitePixel(p);
1127 
1128   XFillRectangle(p->display, p->canvas_pixmap, p->gc_background, 0, 0,
1129 		 p->canvas_width, p->canvas_height);
1130   OutputMessage(p, "Now initializing XStarRoll and making data.");
1131   OutputMessage(p, "Please wait for some minutes...");
1132 
1133   while (*argc > 1) {
1134     if (!strcmp(argv[1], "-")) {
1135       OutputMessage(p, "Writing letters from the standard input.");
1136       if (isatty(fileno(stdin)) != 0)
1137 	OutputMessage(p, "Please input letters and hit Ctrl-D.");
1138       WriteLetters(p, stdin, READ_FROM_FILE);
1139       OutputMessage(p, "Done.");
1140       DeleteParameter(argc, argv, 1);
1141     } else if ((fp = fopen(argv[1], "rt")) == NULL) {
1142       OutputMessage(p, "Writing letters.");
1143       WriteLetters(p, argv[1], READ_FROM_STRING);
1144       OutputMessage(p, "Done.");
1145       DeleteParameter(argc, argv, 1);
1146     } else {
1147       if ( (fgets(tmp_buffer, 10, fp) != NULL) &&
1148 	   (!strcmp(tmp_buffer, "/* XPM */")) ) {
1149 	fclose(fp);
1150 	strcpy(tmp_buffer, "Drawing a pixmap \"");
1151 	strncat(tmp_buffer, argv[1], TMP_BUFFER_SIZE - 100);
1152 	strcat(tmp_buffer, "\".");
1153 	OutputMessage(p, tmp_buffer);
1154 	DrawPixmap(p, argv[1]);
1155 	OutputMessage(p, "Done.");
1156 	DeleteParameter(argc, argv, 1);
1157       } else {
1158 	fclose(fp);
1159 	strcpy(tmp_buffer, "Writing letters in a file \"");
1160 	strncat(tmp_buffer, argv[1], TMP_BUFFER_SIZE - 100);
1161 	strcat(tmp_buffer, "\".");
1162 	OutputMessage(p, tmp_buffer);
1163 	fp = fopen(argv[1], "rt");
1164 	WriteLetters(p, fp, READ_FROM_FILE);
1165 	OutputMessage(p, "Done.");
1166 	fclose(fp);
1167 	DeleteParameter(argc, argv, 1);
1168       }
1169     }
1170   }
1171 
1172   if ( (isatty(fileno(stdin)) == 0) && (feof(stdin) == 0) ){
1173     OutputMessage(p, "Writing letters from the standard input.");
1174     WriteLetters(p, stdin, READ_FROM_FILE);
1175     OutputMessage(p, "Done.");
1176   }
1177   if (p->source_data->start == (SourceData *)NULL) {
1178     OutputMessage(p, "Writing default letters.");
1179     WriteLetters(p, help_string, READ_FROM_STRING);
1180     OutputMessage(p, "Done.");
1181   }
1182   FreeFontData(p);
1183   OutputMessage(p, "Now starting XStarRoll!");
1184   sleep(1);
1185 }
1186 
Quit(XStarRoll * p)1187 void Quit(XStarRoll * p)
1188 {
1189   FreeSourceDataList(p->source_data);
1190   FreeGCBufferList(p->display, p->gc_buffer);
1191   XFreeGC(p->display, p->gc_foreground);
1192   XFreeGC(p->display, p->gc_background);
1193   XFreeGC(p->display, p->gc_copy);
1194   XFreePixmap(p->display, p->canvas_pixmap);
1195   XFreePixmap(p->display, p->icon_pixmap);
1196   XtUnmanageChild(p->canvas);
1197   XtDestroyWidget(p->canvas);
1198   XtDestroyWidget(p->toplevel);
1199   exit (0);
1200 }
1201 
PushKey(Widget w,XtPointer pp,XEvent * event,Boolean * dispatch)1202 void PushKey(Widget w, XtPointer pp, XEvent * event, Boolean * dispatch)
1203 {
1204   XStarRoll * p;
1205   KeySym ks;
1206 
1207   p = (XStarRoll *)pp;
1208   if (event->type == KeyPress) {
1209     ks = XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0);
1210     if      (ks == XK_q        ) Quit(p);
1211     else if (ks == XK_s        ) p->start = 0;
1212     else if (ks == XK_n        ) (p->start)++;
1213     else if (ks == XK_p        ) (p->start)--;
1214     else if (ks == XK_Page_Down) (p->start) += 10;
1215     else if (ks == XK_Page_Up  ) (p->start) -= 10;
1216     else if (ks == XK_a        ) (p->scroll)++;
1217     else if (ks == XK_d        ) (p->scroll)--;
1218     else if (ks == XK_Down     ) (p->length_y)++;
1219     else if (ks == XK_Up       ) {if (p->length_y > 1) (p->length_y)--;}
1220     else if (ks == XK_Right    ) (p->length_x)++;
1221     else if (ks == XK_Left     ) {if (p->length_x > 1) (p->length_x)--;}
1222     p->draw_flag = ON;
1223   }
1224 }
1225 
ExposeCanvas(Widget w,XtPointer pp,XEvent * event,Boolean * dispatch)1226 void ExposeCanvas(Widget w, XtPointer pp, XEvent * event, Boolean * dispatch)
1227 {
1228   XStarRoll * p;
1229 
1230   p = (XStarRoll *)pp;
1231   if (event->type == Expose)
1232     XSetWindowBackgroundPixmap(p->display, p->canvas_window, p->canvas_pixmap);
1233     XClearWindow(p->display, p->canvas_window);
1234     /*
1235     XCopyArea(p->display, p->canvas_pixmap, p->canvas_window, p->gc_copy,
1236 	      event->xexpose.x, event->xexpose.y,
1237 	      event->xexpose.width, event->xexpose.height,
1238 	      event->xexpose.x, event->xexpose.y);
1239 	      */
1240 }
1241 
ResizeCanvas(XStarRoll * p)1242 void ResizeCanvas(XStarRoll * p)
1243 {
1244   int i, n;
1245   Arg args[10];
1246 
1247   n = 0;
1248   XtSetArg(args[n], XtNwidth,  &(p->canvas_width)); n++;
1249   XtSetArg(args[n], XtNheight, &(p->canvas_height)); n++;
1250   XtGetValues(p->toplevel, args, n);
1251   XResizeWindow(p->display, p->canvas_window,
1252 		p->canvas_width, p->canvas_height);
1253   XFreePixmap(p->display, p->canvas_pixmap);
1254   p->canvas_pixmap = XCreatePixmap(p->display, p->toplevel_window,
1255 				   p->canvas_width, p->canvas_height,
1256 				   p->depth);
1257   p->draw_flag = ON;
1258 }
1259 
CanvasEvent(Widget w,XtPointer pp,XEvent * event,Boolean * dispatch)1260 void CanvasEvent(Widget w, XtPointer pp, XEvent * event, Boolean * dispatch)
1261 {
1262   XStarRoll * p;
1263 
1264   p = (XStarRoll *)pp;
1265   if (event->type == ConfigureNotify) ResizeCanvas(p);
1266   else if (event->type == ClientMessage) {
1267     if ( (event->xclient.message_type == p->atom_1) &&
1268 	 (event->xclient.data.l[0] == p->atom_2) ) Quit(p);
1269   }
1270 }
1271 
AddEvents(XStarRoll * p)1272 void AddEvents(XStarRoll * p)
1273 {
1274   XtAddEventHandler(p->toplevel, ExposureMask, False, ExposeCanvas, p);
1275   if (p->root_flag == OFF) {
1276     XtAddEventHandler(p->toplevel, KeyPressMask, False, PushKey, p);
1277     XtAddEventHandler(p->toplevel, StructureNotifyMask, True, CanvasEvent, p);
1278   }
1279 }
1280 
SetIcon(XStarRoll * p)1281 void SetIcon(XStarRoll * p)
1282 {
1283   XWMHints wmh;
1284 
1285   if (p->root_flag == OFF) {
1286     p->icon_pixmap = MakePixmapFromData(p, XSTARROLL_ICON,
1287 					&(p->icon_width), &(p->icon_height));
1288     wmh.flags = IconPixmapHint;
1289     wmh.icon_pixmap = p->icon_pixmap;
1290     XSetWMHints(p->display, p->toplevel_window, &wmh);
1291   }
1292 }
1293 
SetWindowAttributes(XStarRoll * p)1294 void SetWindowAttributes(XStarRoll * p)
1295 {
1296   XWMHints wmhints;
1297 
1298   if (p->root_flag == OFF) {
1299     XtSetSensitive(p->toplevel, True);
1300     XtSetSensitive(p->canvas, True);
1301 
1302     /*
1303     XSelectInput(p->display, p->canvas_window,
1304 		 KeyPressMask | ExposureMask);
1305     XSelectInput(p->display, p->toplevel_window, StructureNotifyMask);
1306     */
1307 
1308     wmhints.input = True;
1309     XSetWMHints(p->display, p->toplevel_window, &wmhints);
1310     p->atom_1 = XInternAtom(p->display, "WM_PROTOCOLS", False);
1311     p->atom_2 = XInternAtom(p->display, "WM_DELETE_WINDOW", False);
1312     XSetWMProtocols(p->display, p->toplevel_window, &(p->atom_2), 1);
1313     XStoreName(p->display, p->toplevel_window, p->title_name);
1314     XSetIconName(p->display, p->toplevel_window, p->title_name);
1315     SetIcon(p);
1316   }
1317 }
1318 
GetCanvasPointY(XStarRoll * p,long int y)1319 double GetCanvasPointY(XStarRoll * p, long int y)
1320 {
1321   return (((double)(p->length_y) * p->canvas_height) / (y + p->length_y));
1322 }
1323 
GetCanvasPointX(XStarRoll * p,long int x,double canvas_y)1324 double GetCanvasPointX(XStarRoll * p, long int x, double canvas_y)
1325 {
1326   return (canvas_y * (x - p->source_width / 2) * p->canvas_width /
1327 	  (p->canvas_height * p->length_x) + p->canvas_width / 2);
1328 }
1329 
DrawCanvasBlurred(XStarRoll * p)1330 void DrawCanvasBlurred(XStarRoll * p)
1331 {
1332   long int x, y;
1333   short int canvas_iy0, canvas_iy1;
1334   double canvas_dy0, canvas_dy1;
1335   XPoint points[4];
1336   SourceData * sp;
1337 
1338   x = y = 0;
1339   sp = p->source_data->start;
1340   canvas_dy0 = GetCanvasPointY(p, p->start - y);
1341   canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1342   canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1343   canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1344 
1345   while ( (y <= p->start) && (sp != (SourceData *)NULL) ) {
1346     if (sp->gc_buffer->pixel != p->background_pixel) {
1347       if (canvas_iy0 == canvas_iy1);
1348       else if (canvas_iy0 == canvas_iy1 + 1) {
1349 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1350 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1351 						  canvas_dy0) + 0.5);
1352 	if (points[0].x == points[3].x);
1353 	else {
1354 	  points[1].x = (short int)
1355 	    (GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1356 	  points[2].x = (short int)
1357 	    (GetCanvasPointX(p, x + sp->length, canvas_dy1) + 0.5);
1358 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1359 		    points[1].x, canvas_iy1, points[2].x, canvas_iy1);
1360 	}
1361       } else {
1362 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1363 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1364 						  canvas_dy0) + 0.5);
1365 	if (points[0].x == points[3].x);
1366 	else {
1367 	  points[1].x = (short int)
1368 	    (GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1369 	  points[2].x = (short int)
1370 	    (GetCanvasPointX(p, x + sp->length, canvas_dy1) + 0.5);
1371 	  if (points[1].x == points[2].x) {
1372 	    points[0].y = canvas_iy0;
1373 	    points[1].y = canvas_iy1;
1374 	    points[2].x = points[3].x;
1375 	    points[2].y = canvas_iy0;
1376 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1377 			 points, 3, Convex, CoordModeOrigin);
1378 	  } else {
1379 	    points[0].y = points[3].y = canvas_iy0;
1380 	    points[1].y = points[2].y = canvas_iy1;
1381 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1382 			 points, 4, Convex, CoordModeOrigin);
1383 	  }
1384 	}
1385       }
1386     }
1387     x += sp->x;
1388     if (sp->y != 0) {
1389       y += sp->y;
1390       if (y <= p->start) {
1391 	canvas_dy0 = GetCanvasPointY(p, p->start - y);
1392 	canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1393 	canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1394 	canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1395       }
1396     }
1397     sp = sp->next;
1398   }
1399 }
1400 
DrawCanvasNoBlurred(XStarRoll * p)1401 void DrawCanvasNoBlurred(XStarRoll * p)
1402 {
1403   long int x, y;
1404   short int canvas_iy0, canvas_iy1;
1405   double canvas_dy0, canvas_dy1;
1406   XPoint points[4];
1407   SourceData * sp;
1408 
1409   x = y = 0;
1410   sp = p->source_data->start;
1411   canvas_dy0 = GetCanvasPointY(p, p->start - y);
1412   canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1413   canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1414   canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1415 
1416   while ( (y <= p->start) && (sp != (SourceData *)NULL) ) {
1417     if (sp->gc_buffer->pixel != p->background_pixel) {
1418       if (canvas_iy0 == canvas_iy1) {
1419 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1420 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1421 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1422 						  canvas_dy0) + 0.5);
1423 	if (points[0].x == points[3].x)
1424 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1425 		     points[1].x, canvas_iy1);
1426 	else if (points[0].x == points[3].x - 1)
1427 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1428 		     points[1].x, canvas_iy1);
1429 	else {
1430 	  points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1431 						    canvas_dy1) + 0.5);
1432 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1433 		    points[1].x, canvas_iy1, points[2].x, canvas_iy1);
1434 	}
1435       } else if (canvas_iy0 == canvas_iy1 + 1) {
1436 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1437 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1438 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1439 						  canvas_dy0) + 0.5);
1440 	if (points[0].x == points[3].x)
1441 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1442 		     points[1].x, canvas_iy1);
1443 	else {
1444 	  points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1445 						    canvas_dy1) + 0.5);
1446 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1447 		    points[1].x, canvas_iy1, points[2].x, canvas_iy1);
1448 	}
1449       } else {
1450 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1451 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1452 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1453 						  canvas_dy0) + 0.5);
1454 	if (points[0].x == points[3].x)
1455 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1456 		    points[1].x, canvas_iy1, points[0].x, canvas_iy0);
1457 	else {
1458 	  points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1459 						    canvas_dy1) + 0.5);
1460 	  if (points[1].x == points[2].x) {
1461 	    points[0].y = canvas_iy0;
1462 	    points[1].y = canvas_iy1;
1463 	    points[2].x = points[3].x;
1464 	    points[2].y = canvas_iy0;
1465 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1466 			 points, 3, Convex, CoordModeOrigin);
1467 	  } else {
1468 	    points[0].y = points[3].y = canvas_iy0;
1469 	    points[1].y = points[2].y = canvas_iy1;
1470 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1471 			 points, 4, Convex, CoordModeOrigin);
1472 	  }
1473 	}
1474       }
1475     }
1476     x += sp->x;
1477     if (sp->y != 0) {
1478       y += sp->y;
1479       if (y <= p->start) {
1480 	canvas_dy0 = GetCanvasPointY(p, p->start - y);
1481 	canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1482 	canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1483 	canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1484       }
1485     }
1486     sp = sp->next;
1487   }
1488 }
1489 
DrawCanvasFilled(XStarRoll * p)1490 void DrawCanvasFilled(XStarRoll * p)
1491 {
1492   long int x, y;
1493   short int canvas_iy0, canvas_iy1;
1494   double canvas_dy0, canvas_dy1;
1495   XPoint points[4];
1496   SourceData * sp;
1497 
1498   x = y = 0;
1499   sp = p->source_data->start;
1500   canvas_dy0 = GetCanvasPointY(p, p->start - y);
1501   canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1502   canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1503   canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1504 
1505   while ( (y <= p->start) && (sp != (SourceData *)NULL) ) {
1506     if (sp->gc_buffer->pixel != p->background_pixel) {
1507       if (canvas_iy0 == canvas_iy1) {
1508 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1509 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1510 	points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1511 						  canvas_dy1) + 0.5);
1512 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1513 						  canvas_dy0) + 0.5);
1514 	if (points[0].x == points[3].x) {
1515 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1516 		     points[0].x, canvas_iy0);
1517 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1518 		     points[1].x, canvas_iy1);
1519 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1520 		     points[2].x, canvas_iy1);
1521 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1522 		     points[3].x, canvas_iy0);
1523 	} else {
1524 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1525 		    points[1].x, canvas_iy1, points[2].x, canvas_iy1);
1526 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1527 		    points[0].x, canvas_iy0, points[3].x, canvas_iy0);
1528 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1529 		     points[2].x, canvas_iy1);
1530 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1531 		     points[3].x, canvas_iy0);
1532 	}
1533       } else if (canvas_iy0 == canvas_iy1 + 1) {
1534 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1535 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1536 	points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1537 						  canvas_dy1) + 0.5);
1538 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1539 						  canvas_dy0) + 0.5);
1540 	if (points[0].x == points[3].x) {
1541 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1542 		     points[0].x, canvas_iy0);
1543 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1544 		     points[1].x, canvas_iy1);
1545 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1546 		     points[2].x, canvas_iy1);
1547 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1548 		     points[3].x, canvas_iy0);
1549 	} else {
1550 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1551 		    points[1].x, canvas_iy1, points[2].x, canvas_iy1);
1552 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1553 		    points[0].x, canvas_iy0, points[3].x, canvas_iy0);
1554 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1555 		     points[2].x, canvas_iy1);
1556 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1557 		     points[3].x, canvas_iy0);
1558 	}
1559       } else {
1560 	points[0].x = (short int)(GetCanvasPointX(p, x, canvas_dy0) + 0.5);
1561 	points[1].x = (short int)(GetCanvasPointX(p, x, canvas_dy1) + 0.5);
1562 	points[2].x = (short int)(GetCanvasPointX(p, x + sp->length,
1563 						  canvas_dy1) + 0.5);
1564 	points[3].x = (short int)(GetCanvasPointX(p, x + sp->length,
1565 						  canvas_dy0) + 0.5);
1566 	if (points[0].x == points[3].x) {
1567 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1568 		    points[1].x, canvas_iy1, points[0].x, canvas_iy0);
1569 	  XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1570 		    points[2].x, canvas_iy1, points[3].x, canvas_iy0);
1571 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1572 		     points[0].x, canvas_iy0);
1573 	  XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1574 		     points[3].x, canvas_iy0);
1575 	} else {
1576 	  if (points[1].x == points[2].x) {
1577 	    points[0].y = canvas_iy0;
1578 	    points[1].y = canvas_iy1;
1579 	    points[2].x = points[3].x;
1580 	    points[2].y = canvas_iy0;
1581 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1582 			 points, 3, Convex, CoordModeOrigin);
1583 	    XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1584 		      points[0].x, canvas_iy0, points[2].x, canvas_iy0);
1585 	    XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1586 		      points[1].x, canvas_iy1, points[2].x, canvas_iy0);
1587 	    XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1588 		       points[2].x, canvas_iy0);
1589 	  } else {
1590 	    points[0].y = points[3].y = canvas_iy0;
1591 	    points[1].y = points[2].y = canvas_iy1;
1592 	    XFillPolygon(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1593 			 points, 4, Convex, CoordModeOrigin);
1594 	    XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1595 		      points[0].x, canvas_iy0, points[3].x, canvas_iy0);
1596 	    XDrawLine(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1597 		      points[2].x, canvas_iy1, points[3].x, canvas_iy0);
1598 	    XDrawPoint(p->display, p->canvas_pixmap, sp->gc_buffer->gc,
1599 		       points[3].x, canvas_iy0);
1600 	  }
1601 	}
1602       }
1603     }
1604     x += sp->x;
1605     if (sp->y != 0) {
1606       y += sp->y;
1607       if (y <= p->start) {
1608 	canvas_dy0 = GetCanvasPointY(p, p->start - y);
1609 	canvas_dy1 = GetCanvasPointY(p, p->start - y + 1);
1610 	canvas_iy0 = (short int)(canvas_dy0 + 0.5);
1611 	canvas_iy1 = (short int)(canvas_dy1 + 0.5);
1612       }
1613     }
1614     sp = sp->next;
1615   }
1616 }
1617 
MainStarRoll(caddr_t pp)1618 Boolean MainStarRoll(caddr_t pp)
1619 {
1620   XStarRoll * p;
1621 
1622   p = (XStarRoll *)pp;
1623   if (p->draw_flag == OFF) {
1624     usleep(100000);
1625     if (p->root_flag == ON) {
1626       sleep(5);
1627       p->draw_flag = ON;
1628     }
1629   } else {
1630     XFillRectangle(p->display, p->canvas_pixmap, p->gc_background, 0, 0,
1631 		   p->canvas_width, p->canvas_height);
1632     if (p->blur_flag == ON) DrawCanvasBlurred(p);
1633     else if (p->blur_flag == OFF) DrawCanvasNoBlurred(p);
1634     else DrawCanvasFilled(p);
1635     XSetWindowBackgroundPixmap(p->display, p->canvas_window, p->canvas_pixmap);
1636     XClearWindow(p->display, p->canvas_window);
1637 /*
1638     XCopyArea(p->display, p->canvas_pixmap, p->canvas_window, p->gc_copy,
1639 	      0, 0, p->canvas_width, p->canvas_height, 0, 0);
1640 */
1641     XFlush(p->display);
1642     p->draw_flag = OFF;
1643     if (p->quit_flag == ON) Quit(p);
1644   }
1645   if (p->scroll != 0) {
1646     p->start += p->scroll;
1647     p->draw_flag = ON;
1648   }
1649   usleep(100);
1650   usleep(p->wait);
1651 }
1652 
main(int argc,char ** argv)1653 int main(int argc, char ** argv)
1654 {
1655   XStarRoll xstarroll;
1656 
1657   InitializeParameters(&xstarroll, &argc, argv);
1658   InitializeDisplay(&xstarroll);
1659   InitializeGC(&xstarroll);
1660   SetWindowAttributes(&xstarroll);
1661   AddEvents(&xstarroll);
1662   InitializeStarRoll(&xstarroll, &argc, argv);
1663   XtAppAddWorkProc(xstarroll.app_context,(XtWorkProc)MainStarRoll,&xstarroll);
1664   XtAppMainLoop(xstarroll.app_context);
1665 }
1666 
1667 /*****************************************************************************/
1668 /* End of Program.                                                           */
1669 /*****************************************************************************/
1670