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