1 /* misc.c:
2  *
3  * miscellaneous funcs
4  *
5  * jim frost 10.05.89
6  *
7  * Copyright 1989, 1990, 1991 Jim Frost.
8  * See included file "copyright.h" for complete copyright information.
9  */
10 
11 #include "copyright.h"
12 #include "xloadimage.h"
13 #include "patchlevel"
14 #include <signal.h>
15 #include <stdlib.h>
16 
17 extern int      _Xdebug;
18 extern Display *display;
19 extern int      screen;
20 
signalName(sig)21 static char *signalName(sig)
22      int sig;
23 { static char buf[32];
24 
25   switch (sig) {
26   case SIGSEGV:
27     return("SEGV");
28   case SIGBUS:
29     return("BUS");
30   case SIGFPE:
31     return("FPE");
32   case SIGILL:
33     return("ILL");
34   default:
35     sprintf(buf, "Signal %d", sig);
36     return(buf);
37   }
38 }
39 
memoryExhausted()40 void memoryExhausted()
41 {
42   fprintf(stderr,
43 	  "Memory has been exhausted; operation cannot continue (sorry).\n");
44   if (_Xdebug)
45     abort();
46   else
47     cleanup(-1);
48 }
49 
internalError(sig)50 void internalError(sig)
51      int sig;
52 { static int handling_error= 0;
53   int a, b;
54   Screen *local_screen;
55 
56   switch(handling_error++) {
57   case 0:
58     fprintf(stderr, "\
59 An internal error (%s) has occurred.  If you would like to file a bug\n\
60 report, please send email to %s\n\
61 with a description of how you triggered the bug, the output of xloadimage\n\
62 before the failure, and the following information:\n\n", signalName(sig),
63 	   AUTHOR_EMAIL);
64     fprintf(stderr, "Xloadimage Version %s.%s\n", VERSION, PATCHLEVEL);
65     if (display) {
66       local_screen= ScreenOfDisplay(display, screen);
67       fprintf(stderr, "Server: %s Version %d\n",
68 				ServerVendor(display), VendorRelease(display));
69       fprintf(stderr, "Depths and visuals supported:\n");
70       for (a= 0; a < local_screen->ndepths; a++) {
71 	fprintf(stderr, "%2d:", local_screen->depths[a].depth);
72 	for (b= 0; b < local_screen->depths[a].nvisuals; b++)
73 	  fprintf(stderr, " %s", nameOfVisualClass(local_screen->depths[a].visuals[b].class));
74 	fprintf(stderr, "\n");
75       }
76     }
77     else
78       fprintf(stderr, "[No information on server; error occurred before connection]\n");
79     break;
80   case 1:
81     fprintf(stderr, "\
82 An internal error has occurred within the internal error handler.  No more\n\
83 information about the error is available, sorry.\n");
84     break;
85   }
86   if (_Xdebug) /* dump core if -debug is on */
87     abort();
88   cleanup(-1);
89 }
90 
version()91 void version()
92 {
93   fprintf(stderr, "Xloadimage version %s patchlevel %s by Jim Frost.\n",
94 	 VERSION, PATCHLEVEL);
95   fprintf(stderr, "Please send email to %s for\npraise or bug reports.\n",
96 	 AUTHOR_EMAIL);
97 }
98 
usage(name)99 void usage(name)
100      char *name;
101 {
102   version();
103   fprintf(stderr, "\nUsage: %s [global options] {[image options] image_name ...}\n\n",
104 	 tail(name));
105   fprintf(stderr, "\
106 Type `%s -help [option ...]' for information on a particular option, or\n\
107 `%s -help' to enter the interactive help facility.\n", tail(name), tail(name));
108   cleanup(-1);
109 }
110 
tail(path)111 char *tail(path)
112      char *path;
113 { int   s;
114   char *t;
115 
116   t= path;
117   for (s= 0; *(path + s) != '\0'; s++)
118     if (*(path + s) == '/')
119       t= path + s + 1;
120   return(t);
121 }
122 
processImage(disp,scrn,image,options,verbose)123 Image *processImage(disp, scrn, image, options, verbose)
124      Display      *disp;
125      int           scrn;
126      Image        *image;
127      ImageOptions *options;
128      unsigned int  verbose;
129 { Image        *tmpimage;
130   XColor        xcolor;
131   unsigned int  compressed= 0;
132   void          gammacorrect();
133 
134   goodImage(image, "processImage");
135 
136   /* clip the image if requested
137    */
138 
139   if ((options->clipx != 0) || (options->clipy != 0) ||
140       (options->clipw != 0) || (options->cliph != 0)) {
141     if (!options->clipw)
142       options->clipw= image->width;
143     if (!options->cliph)
144       options->cliph= image->height;
145     tmpimage= clip(image, options->clipx, options->clipy,
146 		   (options->clipw ? options->clipw : image->width),
147 		   (options->cliph ? options->cliph : image->height),
148 		   verbose);
149     freeImage(image);
150     image= tmpimage;
151   }
152 
153   if (options->rotate) {
154     tmpimage = rotate(image, options->rotate, verbose);
155     freeImage(image);
156     image = tmpimage;
157   }
158 
159   if (options->xzoom || options->yzoom) { /* zoom image */
160     if (!options->colors && RGBP(image) &&              /* if the image is to */
161 	((!options->xzoom && (options->yzoom > 100)) || /* be blown up, */
162 	 (!options->yzoom && (options->xzoom > 100)) || /* compress before */
163 	 (options->xzoom + options->yzoom > 200))) {    /* doing it */
164       compress_colormap(image, verbose);
165       compressed= 1;
166     }
167     tmpimage= zoom(image, options->xzoom, options->yzoom, verbose);
168     freeImage(image);
169     image= tmpimage;
170   }
171 
172   if (options->gray) /* convert image to grayscale */
173     gray(image, verbose);
174 
175   if (options->normalize) { /* normalize image */
176     tmpimage= normalize(image, verbose);
177     if (tmpimage != image) {
178       freeImage(image);
179       image= tmpimage;
180     }
181   }
182 
183   if (options->bright) /* alter image brightness */
184     brighten(image, options->bright, verbose);
185 
186   if (options->gamma != 1.0) /* do display gamma compensation */
187     gammacorrect(image, options->gamma, verbose);
188 
189   /* forcibly reduce colormap
190    */
191 
192   if (options->colors && RGBP(image) && (options->colors < image->rgb.used)) {
193     tmpimage= reduce(image, options->colors, verbose);
194     if (tmpimage != image) {
195       freeImage(image);
196       image= tmpimage;
197     }
198     image->rgb.size= options->colors; /* lie */
199     compressed= 1;
200   }
201 
202   if (options->dither && (image->depth > 1)) { /* image is to be dithered */
203     if (options->dither == 1)
204       tmpimage= dither(image, verbose);
205     else
206       tmpimage= halftone(image, verbose);
207     freeImage(image);
208     image= tmpimage;
209   }
210   else if (!compressed)       /* make sure colormap is minimized */
211     compress_colormap(image, verbose);
212 
213   if (options->smooth > 0) { /* image is to be smoothed */
214     tmpimage= smooth(image, options->smooth, verbose);
215     if (tmpimage != image) {
216       freeImage(image);
217       image= tmpimage;
218     }
219   }
220 
221   /* set foreground and background colors of mono image
222    */
223 
224   xcolor.flags= DoRed | DoGreen | DoBlue;
225   if ((image->depth == 1) && options->fg) {
226     XParseColor(disp, DefaultColormap(disp, scrn), options->fg, &xcolor);
227     *(image->rgb.red + 1)= xcolor.red;
228     *(image->rgb.green + 1)= xcolor.green;
229     *(image->rgb.blue + 1)= xcolor.blue;
230   }
231   if ((image->depth == 1) && options->bg) {
232     XParseColor(disp, DefaultColormap(disp, scrn), options->bg, &xcolor);
233     *image->rgb.red= xcolor.red;
234     *image->rgb.green= xcolor.green;
235     *image->rgb.blue= xcolor.blue;
236   }
237   return(image);
238 }
239 
240 /* simple error handler.  this provides us with some kind of error recovery.
241  */
242 
errorHandler(disp,error)243 int errorHandler(disp, error)
244      Display *disp;
245      XErrorEvent *error;
246 { char errortext[BUFSIZ];
247 
248   XGetErrorText(disp, error->error_code, errortext, BUFSIZ);
249   fprintf(stderr, "xloadimage: X Error: %s on 0x%lx\n",
250 	  errortext, error->resourceid);
251   if (_Xdebug) /* if -debug mode is enabled, dump a core when we hit this */
252     abort();
253   else
254     return(0);
255 }
256 
257 /*
258   strstr - public-domain implementation of standard C library function
259 
260   last edit:	02-Sep-1990	D A Gwyn
261 
262   This is an original implementation based on an idea by D M Sunday,
263   essentially the "quick search" algorithm described in CACM V33 N8.
264   Unlike Sunday's implementation, this one does not wander past the
265   ends of the strings (which can cause malfunctions under certain
266   circumstances), nor does it require the length of the searched
267   text to be determined in advance.  There are numerous other subtle
268   improvements too.  The code is intended to be fully portable, but in
269   environments that do not conform to the C standard, you should check
270   the sections below marked "configure as required".  There are also
271   a few compilation options, as follows:
272 */
273 
274 #ifndef UCHAR_MAX
275 #define UCHAR_MAX 255
276 #endif
277 
278 typedef unsigned char cuc;	/* char variety used in algorithm */
279 
280 #define EOS '\0'		/* C string terminator */
281 
282 char *					/* returns -> leftmost occurrence,
283 					   or null pointer if not present */
vstrstr(s1,s2)284 vstrstr( s1, s2 )
285      char	*s1;		/* -> string to be searched */
286      char	*s2;		/* -> search-pattern string */
287 {
288   register cuc	*t;		/* -> text character being tested */
289   register cuc	*p;		/* -> pattern char being tested */
290   register cuc	*tx;		/* -> possible start of match */
291   register unsigned int	m;      /* length of pattern */
292   register cuc	*top;		/* -> high water mark in text */
293   unsigned int  shift[UCHAR_MAX + 1];	/* pattern shift table */
294 
295   if ( s1 == NULL || s2 == NULL )
296     return NULL;		/* certainly, no match is found! */
297 
298   /* Precompute shift intervals based on the pattern;
299      the length of the pattern is determined as a side effect: */
300 
301   memset(&shift[1], 0, 255);
302 
303   /* Note: shift[0] is undefined at this point (fixed later). */
304 
305   for ( m = 1, p = (cuc *)s2; *p != EOS; ++m, ++p )
306     shift[(cuc)*p] = m;
307 
308   {
309     register unsigned char c;
310 
311     c = UCHAR_MAX;
312     do
313       shift[c] = m - shift[c];
314     while ( --c > 0 );
315     /* Note: shift[0] is still undefined at this point. */
316   }
317 
318   shift[0] = --m; 		/* shift[EOS]; important details! */
319 
320   /* Try to find the pattern in the text string: */
321 
322   for ( top = tx = (cuc *)s1; ; tx += shift[*(top = t)] ) {
323     for ( t = tx, p = (cuc *)s2; ; ++t, ++p ) {
324       if ( *p == EOS )       /* entire pattern matched */
325 	return (char *)tx;
326       if ( *p != *t )
327 	break;
328     }
329     if ( t < top ) /* idea due to ado@elsie.nci.nih.gov */
330       t = top;	   /* already scanned this far for EOS */
331     do	{
332       if ( *t == EOS )
333 	return NULL;	/* no match */
334     } while ( ++t - tx != m );	/* < */
335   }
336 }
337 
338