Partially sync files.el from XEmacs 21.5 for wildcard support.
[sxemacs] / src / media / gif_io.c
1 #include <config.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9 #include "ui/gifrlib.h"
10 #include "sysfile.h"
11
12 /******************************************************************************
13 * Set up the GifFileType structure for use.  This must be called first in any *
14 * client program.  Then, if custom IO or Error functions are desired, call    *
15 * GifSetIOFunc/GifSetErrorFunc, then call EGifInitWrite.  Else call           *
16 * EGifOpenFileName or EGifOpenFileHandle for standard IO functions.           *
17 * If setup fails, a NULL pointer is returned.                                 *
18 ******************************************************************************/
19 GifFileType *GifSetup(void)
20 {
21         GifIODataType *GifIO;
22         GifFileType *GifFile;
23
24         if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL)
25                 return NULL;
26         memset(GifFile, '\0', sizeof(GifFileType));
27         if ((GifIO = (GifIODataType *) malloc(sizeof(GifIODataType))) == NULL) {
28                 free((char *)GifFile);
29                 return NULL;
30         }
31         memset(GifIO, '\0', sizeof(GifIODataType));
32         GifFile->GifIO = GifIO;
33         return GifFile;
34 }
35
36 void GifFree(GifFileType * GifFile)
37 {
38         GifFilePrivateType *Private;
39
40         if (GifFile == NULL)
41                 return;
42
43         Private = (GifFilePrivateType *) GifFile->Private;
44
45         if (GifFile->SavedImages)
46                 FreeSavedImages(GifFile);
47         if (GifFile->Image.ColorMap)
48                 FreeMapObject(GifFile->Image.ColorMap);
49         if (GifFile->SColorMap)
50                 FreeMapObject(GifFile->SColorMap);
51         if (Private) {
52                 free(Private);
53         }
54         if (GifFile->GifIO)
55                 free(GifFile->GifIO);
56         free(GifFile);
57 }
58
59 /****************************************************************************
60 * Install the specified ReadFunction into the GifFile specified.            *
61 ****************************************************************************/
62 void GifSetReadFunc(GifFileType * GifFile, Gif_rw_func ReadFunc, VoidPtr data)
63 {
64         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
65         GifIO->ReadFunc = ReadFunc;
66         GifIO->ReadFunc_data = data;
67 }
68
69 /****************************************************************************
70 * Install the specified WriteFunction into the GifFile specified.           *
71 ****************************************************************************/
72 void GifSetWriteFunc(GifFileType * GifFile, Gif_rw_func WriteFunc, VoidPtr data)
73 {
74         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
75         GifIO->WriteFunc = WriteFunc;
76         GifIO->WriteFunc_data = data;
77 }
78
79 /****************************************************************************
80 * Install the specified CloseFunction into the GifFile specified.           *
81 ****************************************************************************/
82 void GifSetCloseFunc(GifFileType * GifFile, Gif_close_func CloseFunc,
83                      VoidPtr data)
84 {
85         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
86         GifIO->CloseFunc = CloseFunc;
87         GifIO->CloseFunc_data = data;
88 }
89
90 /****************************************************************************
91 * Install the standard IO funcs into the GifFile, including the FILE info   *
92 ****************************************************************************/
93 void GifStdIOInit(GifFileType * GifFile, FILE * file, int filehandle)
94 {
95         GifStdIODataType *IOData;
96
97         if ((IOData =
98              (GifStdIODataType *) malloc(sizeof(GifStdIODataType))) == NULL)
99                 GifInternError(GifFile, GIF_ERR_NOT_ENOUGH_MEM);
100         IOData->File = file;
101         IOData->FileHandle = filehandle;
102         GifSetReadFunc(GifFile, GifStdRead, IOData);
103         GifSetWriteFunc(GifFile, GifStdWrite, IOData);
104         GifSetCloseFunc(GifFile, GifStdFileClose, IOData);
105 }
106
107 size_t GifStdRead(GifByteType * buf, size_t size, VoidPtr method_data)
108 {
109         GifStdIODataType *IOtype = (GifStdIODataType *) method_data;
110         return (fread(buf, 1, size, IOtype->File));
111 }
112
113 size_t GifStdWrite(GifByteType * buf, size_t size, VoidPtr method_data)
114 {
115         GifStdIODataType *IOtype = (GifStdIODataType *) method_data;
116         return (fwrite(buf, 1, size, IOtype->File));
117 }
118
119 int GifStdFileClose(VoidPtr method_data)
120 {
121         int ret;
122         GifStdIODataType *IOtype = (GifStdIODataType *) method_data;
123         ret = fclose(IOtype->File);
124         if (ret == 0 && IOtype->FileHandle != -1)
125                 ret = close(IOtype->FileHandle);
126         return ret;
127 }
128
129 void GifRead(GifByteType * buf, size_t size, GifFileType * GifFile)
130 {
131         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
132         if ((*(GifIO->ReadFunc)) (buf, size, GifIO->ReadFunc_data) != size)
133                 GifError(GifFile, "Read error!");
134 }
135
136 void GifWrite(GifByteType * buf, size_t size, GifFileType * GifFile)
137 {
138         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
139         if ((*(GifIO->WriteFunc)) (buf, size, GifIO->WriteFunc_data) != size)
140                 GifError(GifFile, "Write error!");
141 }
142
143 int GifClose(GifFileType * GifFile)
144 {
145         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
146         return ((*(GifIO->CloseFunc)) (GifIO->CloseFunc_data));
147 }
148
149 static char *GifErrorString[14] = {
150         "Failed to open given file",    /* D_GIF_ERR_OPEN_FAILED */
151         "Failed to read from given file",       /* D_GIF_ERR_READ_FAILED */
152         "Given file is NOT a GIF file", /* D_GIF_ERR_NOT_GIF_FILE */
153         "No Screen Descriptor detected",        /* D_GIF_ERR_NO_SCRN_DSCR */
154         "No Image Descriptor detected", /* D_GIF_ERR_NO_IMAG_DSCR */
155         "No global or local color map", /* D_GIF_ERR_NO_COLOR_MAP */
156         "Wrong record type detected",   /* D_GIF_ERR_WRONG_RECORD */
157         "#Pixels bigger than Width * Height",   /* D_GIF_ERR_DATA_TOO_BIG */
158         "Fail to allocate required memory",     /* D_GIF_ERR_NOT_ENOUGH_MEM */
159         "Failed to close given file",   /* D_GIF_ERR_CLOSE_FAILED */
160         "Given file was not opened for read",   /* D_GIF_ERR_CLOSE_FAILED */
161         "Image is defective, decoding aborted", /* D_GIF_ERR_IMAGE_DEFECT */
162         "Image EOF detected before image complete",     /* D_GIF_ERR_EOF_TOO_SOON */
163         "Undefined error!",
164 };
165
166 const char *GetGifError(int error);
167
168 /*****************************************************************************
169 * Get the last GIF error in human-readable form.                             *
170 *****************************************************************************/
171 const char *GetGifError(int error)
172 {
173         char *Err;
174
175         switch (error) {
176         case D_GIF_ERR_OPEN_FAILED:
177                 Err = GifErrorString[0];
178                 break;
179         case D_GIF_ERR_READ_FAILED:
180                 Err = GifErrorString[1];
181                 break;
182         case D_GIF_ERR_NOT_GIF_FILE:
183                 Err = GifErrorString[2];
184                 break;
185         case D_GIF_ERR_NO_SCRN_DSCR:
186                 Err = GifErrorString[3];
187                 break;
188         case D_GIF_ERR_NO_IMAG_DSCR:
189                 Err = GifErrorString[4];
190                 break;
191         case D_GIF_ERR_NO_COLOR_MAP:
192                 Err = GifErrorString[5];
193                 break;
194         case D_GIF_ERR_WRONG_RECORD:
195                 Err = GifErrorString[6];
196                 break;
197         case D_GIF_ERR_DATA_TOO_BIG:
198                 Err = GifErrorString[7];
199                 break;
200         case D_GIF_ERR_NOT_ENOUGH_MEM:
201                 Err = GifErrorString[8];
202                 break;
203         case D_GIF_ERR_CLOSE_FAILED:
204                 Err = GifErrorString[9];
205                 break;
206         case D_GIF_ERR_NOT_READABLE:
207                 Err = GifErrorString[10];
208                 break;
209         case D_GIF_ERR_IMAGE_DEFECT:
210                 Err = GifErrorString[11];
211                 break;
212         case D_GIF_ERR_EOF_TOO_SOON:
213                 Err = GifErrorString[12];
214                 break;
215         default:
216                 Err = GifErrorString[13];
217                 break;
218         }
219         return Err;
220 }
221
222 /******************************
223 * These are called internally *
224 ******************************/
225 void GifError(GifFileType * GifFile, const char *err_str)
226 {
227         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
228         if (GifIO->ErrorFunc)
229                 (*(GifIO->ErrorFunc)) (err_str, GifIO->ErrorFunc_data);
230         else
231                 fprintf(stderr, "GIF FATAL ERROR: %s", err_str);
232         exit(-10);
233 }
234
235 void GifWarning(GifFileType * GifFile, const char *err_str)
236 {
237         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
238         if (GifIO->WarningFunc)
239                 (*(GifIO->WarningFunc)) (err_str, GifIO->WarningFunc_data);
240 }
241
242 void GifInternError(GifFileType * GifFile, int error_num)
243 {
244         const char *ErrStr = GetGifError(error_num);
245         GifError(GifFile, ErrStr);
246 }
247
248 void GifInternWarning(GifFileType * GifFile, int error_num)
249 {
250         const char *ErrStr = GetGifError(error_num);
251         GifWarning(GifFile, ErrStr);
252 }
253
254 void GifSetErrorFunc(GifFileType * GifFile, Gif_error_func ErrorFunc,
255                      VoidPtr data)
256 {
257         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
258         GifIO->ErrorFunc = ErrorFunc;
259         GifIO->ErrorFunc_data = data;
260 }
261
262 void GifSetWarningFunc(GifFileType * GifFile, Gif_error_func WarningFunc,
263                        VoidPtr data)
264 {
265         GifIODataType *GifIO = (GifIODataType *) GifFile->GifIO;
266         GifIO->WarningFunc = WarningFunc;
267         GifIO->WarningFunc_data = data;
268 }