Back to index

im-sdk  12.3.91
aux_win.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <locale.h>
00046 #include <limits.h>
00047 #include <X11/Xmd.h>
00048 #include <X11/Xatom.h>
00049 #include <X11/Intrinsic.h>
00050 #include <X11/Shell.h>
00051 
00052 #include <Xm/Xm.h>
00053 #include <Xm/RepType.h>
00054 #include <Xm/DialogS.h>
00055 #include <Xm/PushB.h>
00056 #include <Xm/RowColumn.h>
00057 #include <Xm/CascadeB.h>
00058 #include <Xm/MwmUtil.h>
00059 
00060 #include <fcntl.h>
00061 #include "gif_lib.h"
00062 #include "getarg.h"
00063 
00064 #define IMAGE_PATH "/usr/lib/im/locale/zh_CN/newpy/"
00065 
00066 Pixmap LoadGIFFile(char * filename);
00067 static void AllocateColors1(void);
00068 static void AllocateColors2(void);
00069 
00070 void ProcessInitialPropertyNotify(void);
00071 
00072 #define ABS(x)          ((x) > 0 ? (x) : (-(x)))
00073 
00074 /* Global Declarations */
00075 
00076 #define HTT_AUX_EXT_NAME        "sample_ext"
00077 #define HTT_AUX_SO_NAME         "sample_so"
00078 #define HTT_AUX_PROP_NAME       "sample_prop"
00079 #define HTT_AUX_PROP1_NAME      "sample_prop1"
00080 
00081 Atom    aux_so_atom;
00082 Atom    aux_ext_atom;
00083 Atom    aux_prop_atom;
00084 Atom    aux_prop1_atom;
00085 
00086 int             icid;
00087 int             imid;
00088 
00089 Window  aux_window;
00090 
00091 XtAppContext app_context = (XtAppContext) 0 ;
00092 Display     *display     = (Display *)    0 ;
00093 Widget      toplevel;
00094 
00095 static int screen;
00096 static GC gc;
00097 static Colormap colormap;
00098 static long XPixelTable[256];
00099 static XColor XColorTable[256];
00100 static Visual *XVisual;
00101 static ColorMapObject *ColorMap;
00102 
00103 Widget cascade1 = (Widget)NULL;
00104 
00105 int input_mode = 13, quanjiao_mode = 0, gbk_mode = 0;
00106 
00107 static char *button_names[17] = {
00108        "Math     ",
00109               "Digital1 ",
00110               "Digital2 ",
00111               "Digital3 ",
00112               "Roman    ",
00113               "Greek    ",
00114               "Russia   ",
00115               "PY Symbol",
00116               "Japanese1",
00117               "Japanese2",
00118               "Table1   ",
00119               "Table2   ",
00120               "Other    ",
00121               "QuanPin  ",
00122        "ShuangPin",
00123               "ASCII    ",
00124               0 };
00125 
00126 void symbolchange ( Widget w, int client_data, XtPointer call_data ) {
00127        Arg al[20];
00128        int ac;
00129 
00130        XmAnyCallbackStruct *   cb;
00131         char                    p[4];
00132         Display *               display;
00133         Window                  w_so;
00134         unsigned char           buf[1024];
00135         int                     size;
00136 
00137        ac = 0;
00138        XtSetArg(al[ac], XmNlabelString, 
00139               (XmString) XmStringCreateSimple(button_names[client_data])); ac++;
00140        XtSetValues(cascade1, al, ac);
00141 
00142        input_mode = client_data;
00143        p[1] = input_mode + 'a';
00144        p[0] = quanjiao_mode + 'a';
00145        p[2] = gbk_mode + 'a';
00146        p[3] = '\0';
00147        
00148         display = XtDisplay(w);
00149         cb = (XmAnyCallbackStruct *)call_data;
00150 
00151         if (None == (w_so = XGetSelectionOwner(display, aux_so_atom))) {
00152                 return;
00153         }
00154 
00155         buf[0] = ((imid & 0xff00) >> 8);
00156         buf[1] = ((imid & 0x00ff) >> 0);
00157         buf[2] = ((icid & 0xff00) >> 8);
00158         buf[3] = ((icid & 0x00ff) >> 0);
00159         size = strlen(p);
00160         if (((sizeof (buf)) - 4) < size) {
00161                 size = ((sizeof (buf)) - 4);
00162         }
00163         memcpy(buf + 4, p, size);
00164         XChangeProperty(display, w_so, aux_prop_atom, XA_STRING,
00165                         8, PropModeReplace, buf, size + 4);
00166 
00167         XFree(p);
00168 }
00169 
00170 void quanjiaochange ( Widget w, XtPointer client_data, XtPointer call_data )
00171 {
00172        static Pixmap quanjiao_img = (Pixmap) 0, banjiao_img = (Pixmap) 0;
00173        static int first = 1;
00174        char image_path[100];
00175        XmAnyCallbackStruct *   cb;
00176         char                    p[4];
00177         Display *               display;
00178         Window                  w_so;
00179         unsigned char           buf[1024];
00180         int                     size;
00181 
00182        Arg al[20];
00183        int ac;
00184 
00185        if( !quanjiao_img && !banjiao_img ) {
00186               strcpy(image_path, IMAGE_PATH);
00187               strcat(image_path, "full.gif");
00188               quanjiao_img = LoadGIFFile(image_path);
00189               strcpy(image_path, IMAGE_PATH);
00190               strcat(image_path, "half.gif");
00191               banjiao_img = LoadGIFFile(image_path);
00192               quanjiao_mode = 0;
00193        }
00194        else quanjiao_mode = 1 - quanjiao_mode;
00195 
00196        ac = 0;
00197        XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
00198        if (!quanjiao_mode) XtSetArg(al[ac], XmNlabelPixmap, (Pixmap) quanjiao_img);
00199        else  XtSetArg(al[ac], XmNlabelPixmap, (Pixmap) banjiao_img); 
00200        ac++;
00201        XtSetValues(w, al, ac);
00202 
00203        if (first) {
00204               first = 0;
00205               return;
00206        }
00207 
00208        p[1] = input_mode + 'a';
00209        p[0] = quanjiao_mode + 'a';
00210        p[2] = gbk_mode + 'a';
00211        p[3] = '\0';
00212 
00213         display = XtDisplay(w);
00214         cb = (XmAnyCallbackStruct *)call_data;
00215 
00216         if (None == (w_so = XGetSelectionOwner(display, aux_so_atom))) {
00217                 return;
00218         }
00219 
00220         buf[0] = ((imid & 0xff00) >> 8);
00221         buf[1] = ((imid & 0x00ff) >> 0);
00222         buf[2] = ((icid & 0xff00) >> 8);
00223         buf[3] = ((icid & 0x00ff) >> 0);
00224         size = strlen(p);
00225         if (((sizeof (buf)) - 4) < size) {
00226                 size = ((sizeof (buf)) - 4);
00227         }
00228         memcpy(buf + 4, p, size);
00229         XChangeProperty(display, w_so, aux_prop_atom, XA_STRING,
00230                         8, PropModeReplace, buf, size + 4);
00231 
00232         XFree(p);
00233 }
00234 
00235 void charsetchange ( Widget w, XtPointer client_data, XtPointer call_data )
00236 {
00237         static Pixmap gb_img = (Pixmap) 0, gbk_img = (Pixmap) 0;
00238        char image_path[100];
00239        static int first = 1;
00240        XmAnyCallbackStruct *   cb;
00241         char                    p[4];
00242         Display *               display;
00243         Window                  w_so;
00244         unsigned char           buf[1024];
00245         int                     size;
00246         Arg al[20];
00247         int ac;
00248 
00249         if(!gb_img && !gbk_img ) {
00250               strcpy(image_path, IMAGE_PATH);
00251               strcat(image_path, "gb.gif");
00252                 gb_img = LoadGIFFile(image_path);
00253               strcpy(image_path, IMAGE_PATH);
00254               strcat(image_path, "gbk.gif");
00255                 gbk_img = LoadGIFFile(image_path);
00256                 gbk_mode = 0;
00257         }
00258         else gbk_mode = 1 - gbk_mode;
00259 
00260         ac = 0;
00261         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
00262         if (gbk_mode) XtSetArg(al[ac], XmNlabelPixmap, (Pixmap) gbk_img);
00263         else XtSetArg(al[ac], XmNlabelPixmap, (Pixmap) gb_img); 
00264        ac++;
00265         XtSetValues(w, al, ac);
00266 
00267        if (first) {
00268               first = 0;
00269               return;
00270        }
00271 
00272        p[1] = input_mode + 'a';
00273        p[0] = quanjiao_mode + 'a';
00274        p[2] = gbk_mode + 'a';
00275        p[3] = '\0';
00276        
00277         display = XtDisplay(w);
00278         cb = (XmAnyCallbackStruct *)call_data;
00279 
00280         if (None == (w_so = XGetSelectionOwner(display, aux_so_atom))) {
00281                 return;
00282         }
00283 
00284         buf[0] = ((imid & 0xff00) >> 8);
00285         buf[1] = ((imid & 0x00ff) >> 0);
00286         buf[2] = ((icid & 0xff00) >> 8);
00287         buf[3] = ((icid & 0x00ff) >> 0);
00288         size = strlen(p);
00289         if (((sizeof (buf)) - 4) < size) {
00290                 size = ((sizeof (buf)) - 4);
00291         }
00292         memcpy(buf + 4, p, size);
00293         XChangeProperty(display, w_so, aux_prop_atom, XA_STRING,
00294                         8, PropModeReplace, buf, size + 4);
00295 
00296         XFree(p);
00297 }
00298 
00299 void createGUI (Widget parent)
00300 {
00301        int i;
00302         Arg al[64];           /* Arg List */
00303         int ac = 0;           /* Arg Count */
00304        char image_path[100];
00305 
00306         Widget children[16];      /* Children to manage */
00307 
00308         Widget rowcol1 = (Widget)NULL;
00309         Widget menuBar1 = (Widget)NULL;
00310         Widget menu1 = (Widget)NULL;
00311 
00312         Widget button[16]; 
00313         Widget button16 = (Widget)NULL;
00314         Widget button17 = (Widget)NULL;
00315         Widget button18 = (Widget)NULL;
00316 
00317 
00318 
00319        for(i = 0; i < 16; i ++) button[i] = (Widget) NULL;
00320 
00321         ac = 0;
00322         XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
00323 /*        XtSetArg(al[ac], XmNpacking, XmPACK_COLUMN); ac++;*/
00324         XtSetArg(al[ac], XmNentryAlignment, XmALIGNMENT_CENTER); ac++;
00325         rowcol1 = XmCreateRowColumn ( parent, "rowcol1", al, ac );
00326 
00327         ac = 0;
00328         menuBar1 = XmCreateMenuBar ( rowcol1, "menuBar1", al, ac );
00329 
00330        ac = 0;
00331         cascade1 = XmCreateCascadeButton ( menuBar1, "QuanPin  ", al, ac );
00332 
00333        ac = 0;
00334         menu1 = XmCreatePulldownMenu ( menuBar1, "menu1", al, ac );
00335 
00336        for(i = 0; i < 16; i ++){
00337               ac = 0;
00338                button[i] = XmCreatePushButton ( menu1, button_names[i], al, ac );
00339               XtAddCallback(button[i], XmNactivateCallback, symbolchange, i);
00340        }
00341 
00342        ac = 0;
00343         button16 = XmCreatePushButton ( rowcol1, "qjmode", al, ac );
00344        XtAddCallback(button16, XmNactivateCallback, quanjiaochange, NULL);
00345        quanjiaochange(button16, NULL, NULL);
00346 
00347        ac = 0;
00348         button17 = XmCreatePushButton ( rowcol1, "gbkmode", al, ac );
00349        XtAddCallback(button17, XmNactivateCallback, charsetchange, NULL);
00350        charsetchange(button17, NULL, NULL);
00351 
00352        ac = 0;
00353         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
00354        strcpy(image_path, IMAGE_PATH);
00355        strcat(image_path, "help.gif");
00356         XtSetArg(al[ac], XmNlabelPixmap, (Pixmap)LoadGIFFile(image_path)); ac++;
00357         button18 = XmCreatePushButton ( rowcol1, "help", al, ac );
00358 
00359        ac = 0;
00360        for( i = 0; i < 16; i ++ ) children[ac++] = button[i];
00361         XtManageChildren(children, ac);
00362 
00363         ac = 0;
00364         XtSetArg(al[ac], XmNsubMenuId, menu1); ac++;
00365         XtSetValues(cascade1, al, ac );
00366 
00367         ac = 0;
00368         children[ac++] = cascade1;
00369         XtManageChildren(children, ac);
00370 
00371         ac = 0;
00372         children[ac++] = menuBar1;
00373         children[ac++] = button16;
00374         children[ac++] = button17;
00375         children[ac++] = button18;
00376         XtManageChildren(children, ac);
00377 
00378         XtManageChild ( rowcol1);
00379 }
00380 
00381 int main(int argc, char **argv)
00382 {
00383        Arg al[64];
00384        int ac;
00385        char            atom_name[1024];
00386 
00387        /* Enable Localisation of the Application */
00388        setlocale(LC_ALL, NULL);
00389 
00390        XtSetLanguageProc((XtAppContext) 0, (XtLanguageProc) 0, (XtPointer) 0) ;
00391 
00392        ac = 0;
00393        XtSetArg(al[ac], XmNmwmDecorations, MWM_DECOR_BORDER | MWM_DECOR_TITLE); ac++;
00394        toplevel = XtAppInitialize(&app_context, "aux", NULL, 0,
00395                                    &argc, argv, NULL, al, ac);
00396 
00397        ac = 0;
00398        XtSetArg(al[ac], XmNallowShellResize, False); ac++;
00399        XtSetValues(toplevel, al, ac);
00400 
00401        display = XtDisplay(toplevel);
00402 
00403        screen = DefaultScreen(display);
00404        colormap = DefaultColormap(display, screen);
00405        gc = DefaultGC(display, screen);
00406 
00407        sprintf(atom_name, "htt_%s_%s", *(argv + 0), HTT_AUX_EXT_NAME);
00408         aux_ext_atom = XInternAtom(display, atom_name, False);
00409         sprintf(atom_name, "htt_%s_%s", *(argv + 0), HTT_AUX_SO_NAME);
00410         aux_so_atom = XInternAtom(display, atom_name, False);
00411         sprintf(atom_name, "htt_%s_%s", *(argv + 0), HTT_AUX_PROP_NAME);
00412         aux_prop_atom = XInternAtom(display, atom_name, False);
00413         sprintf(atom_name, "htt_%s_%s", *(argv + 0), HTT_AUX_PROP1_NAME);
00414         aux_prop1_atom = XInternAtom(display, atom_name, False);
00415 
00416         if (None != XGetSelectionOwner(display, aux_ext_atom)) {
00417                 exit(1);
00418         }
00419 
00420        createGUI(toplevel);
00421 
00422        XtRealizeWidget(toplevel);
00423 
00424         aux_window = XtWindow(toplevel);
00425 
00426         if (None != XGetSelectionOwner(display, aux_ext_atom)) {
00427                 exit(1);
00428         }
00429         XSetSelectionOwner(display, aux_ext_atom, aux_window, CurrentTime);
00430         if (aux_window != XGetSelectionOwner(display, aux_ext_atom)) {
00431                 exit(1);
00432         }
00433 
00434 /*
00435         XtAddEventHandler(toplevel, PropertyChangeMask, False,
00436                           AuxEventHandler, NULL);
00437 
00438         XtAddEventHandler(toplevel, NoEventMask, True,
00439                           AuxEventHandler, NULL);
00440 */
00441 
00442         ProcessInitialPropertyNotify();
00443 
00444        XtAppMainLoop (app_context);
00445 }
00446 
00447 void
00448 ProcessInitialPropertyNotify(void)
00449 {
00450         Display *               display;
00451         long                    long_length;
00452         Atom                    actual_type_return;
00453         int                     actual_format_return;
00454         unsigned long           nitem_return;
00455         unsigned long           bytes_after_return;
00456         unsigned char *         prop_return;
00457         int                     r;
00458         XTextProperty           text_prop;
00459         Window                  w_so;
00460         char                    buf[1024];
00461         int                     len;
00462 
00463         display = XtDisplay(toplevel);
00464 
00465         if (None == (w_so = XGetSelectionOwner(display, aux_so_atom))) {
00466                 return;
00467         }
00468 
00469 
00470         r = XGetWindowProperty(display, w_so,
00471                                aux_prop1_atom, 0, INT_MAX, True,
00472                                AnyPropertyType, &actual_type_return,
00473                                &actual_format_return, &nitem_return,
00474                                &bytes_after_return, &prop_return);
00475         if (Success != r) {
00476                 return;
00477         }
00478 
00479         switch (actual_type_return) {
00480         case XA_STRING:
00481                 imid = *((CARD16 *)(prop_return + 0));
00482                 icid = *((CARD16 *)(prop_return + 2));
00483 /*
00484                 len = (((nitem_return - 4) < (sizeof (buf))) ?
00485                        (nitem_return - 4) : ((sizeof (buf)) - 1));
00486                 memcpy(buf, prop_return + 4, len);
00487                 buf[len] = '\0';
00488                 XmTextSetString(input, buf);
00489 */
00490                 break;
00491         case XA_INTEGER:
00492                 break;
00493         }
00494 
00495         XFree(prop_return);
00496         return;
00497 }
00498 
00499 
00500 /* Make some variables global, so we could access them faster: */
00501 
00502 static int
00503     ColorMapSize = 0,
00504     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
00505     InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
00506 
00507 Pixmap LoadGIFFile(char* filename)
00508 {
00509     int i, j, x, y;
00510     int Error, ImageNum = 0, Size, Row, Col, Width, Height, ExtCode, Count;
00511     int ForceFlag = FALSE;
00512 
00513     char *XImageData;
00514     XImage *XImageBuffer;
00515     Pixmap pixmap;
00516     GifFileType *GifFile;
00517     GifRowType *ScreenBuffer;
00518     GifRecordType RecordType;
00519     GifByteType *Extension;
00520 
00521     if ((GifFile = DGifOpenFileName(filename)) == NULL) {
00522             PrintGifError();
00523             exit(-1);
00524     }  
00525 
00526     if ((ScreenBuffer = (GifRowType *)
00527         malloc(GifFile->SHeight * sizeof(GifRowType *))) == NULL) {
00528             printf("Failed to allocate memory required, aborted.");
00529            exit(1);
00530        }
00531 
00532     Size = GifFile->SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/
00533     if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */
00534         printf("Failed to allocate memory required, aborted.");
00535 
00536     for (i = 0; i < GifFile->SWidth; i++)  /* Set its color to BackGround. */
00537         ScreenBuffer[0][i] = GifFile->SBackGroundColor;
00538     for (i = 1; i < GifFile->SHeight; i++) {
00539         /* Allocate the other rows, and set their color to background too: */
00540 
00541         if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL)
00542             printf("Failed to allocate memory required, aborted.");
00543 
00544         memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
00545     }
00546 
00547     /* Scan the content of the GIF file and load the image(s) in: */
00548     do {
00549         if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
00550             PrintGifError();
00551             exit(-1);
00552         }
00553         switch (RecordType) {
00554             case IMAGE_DESC_RECORD_TYPE:
00555                 if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
00556                     PrintGifError();
00557                     exit(-1);
00558                 }
00559                 Row = GifFile->Image.Top; /* Image Position relative to Screen. */
00560                 Col = GifFile->Image.Left;
00561                 Width = GifFile->Image.Width;
00562                 Height = GifFile->Image.Height;
00563                 if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||
00564                    GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) {
00565                     fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n");
00566                     exit(-2);
00567                 }
00568                 if (GifFile->Image.Interlace) {
00569                     /* Need to perform 4 passes on the images: */
00570                     for (Count = i = 0; i < 4; i++)
00571                         for (j = Row + InterlacedOffset[i]; j<Row + Height;
00572                                                  j += InterlacedJumps[i]) {
00573                             if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
00574                                 Width) == GIF_ERROR) {
00575                                 PrintGifError();
00576                                 exit(-1);
00577                             }
00578                         }
00579                 }
00580                 else {
00581                     for (i = 0; i < Height; i++) {
00582                         if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
00583                                 Width) == GIF_ERROR) {
00584                             PrintGifError();
00585                             exit(-1);
00586                         }
00587                     }
00588                 }
00589                 break;
00590             case EXTENSION_RECORD_TYPE:
00591                 /* Skip any extension blocks in file: */
00592                 if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
00593                     PrintGifError();
00594                     exit(-1);
00595                 }
00596                 while (Extension != NULL) {
00597                     if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
00598                         PrintGifError();
00599                         exit(-1);
00600                     }
00601                 }
00602                 break;
00603             case TERMINATE_RECORD_TYPE:
00604                 break;
00605             default:                /* Should be traps by DGifGetRecordType. */
00606                 break;
00607         }
00608     }
00609     while (RecordType != TERMINATE_RECORD_TYPE);
00610 
00611     ColorMap = (GifFile->Image.ColorMap
00612                 ? GifFile->Image.ColorMap
00613                 : GifFile->SColorMap);
00614     ColorMapSize = ColorMap->ColorCount;
00615 
00616     /* The big trick here is to select the colors so lets do this first: */
00617     if (ForceFlag)
00618         AllocateColors2();
00619     else
00620         AllocateColors1();
00621 
00622     /* Create the image in X format: */
00623     if ((XImageData = (char *) malloc(GifFile->SWidth * GifFile->SHeight)) == NULL)
00624         printf("Failed to allocate memory required, aborted.");
00625 
00626     for (i = 0; i < GifFile->SHeight; i++) {
00627         y = i * GifFile->SWidth;
00628         for (j = 0; j < GifFile->SWidth; j++)
00629             XImageData[y + j] = XPixelTable[ScreenBuffer[i][j]];
00630     }
00631     XImageBuffer = XCreateImage(display, XVisual, 8, ZPixmap, 0,
00632                                 XImageData, GifFile->SWidth, GifFile->SHeight,
00633                                 8, GifFile->SWidth);
00634 
00635     pixmap = XCreatePixmap(display, RootWindow(display, screen), GifFile->SWidth, GifFile->SHeight,8);
00636 
00637     XPutImage(display, pixmap, gc, XImageBuffer,0,0,0,0,GifFile->SWidth, GifFile->SHeight);
00638     free(XImageData);
00639     XDestroyImage(XImageBuffer);
00640 
00641     return pixmap;
00642 }
00643 
00644 /******************************************************************************
00645 * Routine to allocate the requested colors from the X server.                 *
00646 * Colors are allocated until success by stripping off the least bits of the   *
00647 * colors.                                                                     *
00648 ******************************************************************************/
00649 static void AllocateColors1(void)
00650 {
00651     int Strip, Msk, i, j;
00652     char Msg[80];
00653 
00654     for (i = 0; i < 256; i++)
00655         XPixelTable[i] = 0;        /* Put reasonable color for out of range. */
00656 
00657     for (Strip = 0, Msk = 0xff; Strip < 8; Strip++, Msk <<= 1) {
00658         for (i = 0; i < ColorMapSize; i++) {
00659             /* Prepere color entry in X format. */
00660             XColorTable[i].red = (ColorMap->Colors[i].Red & Msk) << 8;
00661             XColorTable[i].green = (ColorMap->Colors[i].Green & Msk) << 8;
00662             XColorTable[i].blue = (ColorMap->Colors[i].Blue & Msk) << 8;
00663             XColorTable[i].flags = DoRed | DoGreen | DoBlue;
00664             if (XAllocColor(display, colormap, &XColorTable[i]))
00665                 XPixelTable[i] = XColorTable[i].pixel;
00666             else
00667                 break;
00668         }
00669         if (i < ColorMapSize)
00670             XFreeColors(display, colormap, XPixelTable, i, 0L);
00671         else
00672             break;
00673     }
00674 
00675     if (Strip == 8)
00676         printf("Can not display the image - not enough colors available.");
00677 
00678     if (Strip != 0) {
00679         sprintf(Msg, "%d bits were stripped off the color map.", Strip);
00680         printf(Msg);
00681     }
00682 }
00683 
00684 /******************************************************************************
00685 * Routine to allocate the requested colors from the X server.                 *
00686 * Two stages are performed:                                                   *
00687 * 1. Colors are requested directly.                                           *
00688 * 2. If not enough colors can be allocated, the closest current color         *
00689 *    in current table is selected instead.                                    *
00690 * This allocation is not optimal as when fail to allocate all colors one      *
00691 * should pick the right colors to do allocate in order to minimize the        *
00692 * closest distance from the unallocated ones under some norm (what is a good  *
00693 * norm for the RGB space?). Improve it if you are bored.                      *
00694 ******************************************************************************/
00695 static void AllocateColors2(void)
00696 {
00697     int i, j, Index = 0, Count = 0, XNumOfColors;
00698     char Msg[80];
00699     unsigned long D, Distance, AvgDistance = 0, Red, Green, Blue;
00700     GifBooleanType Failed = FALSE;
00701     XColor *XOldColorTable;
00702 
00703     for (i = 0; i < 256; i++) {
00704         if (i < ColorMapSize) {          /* Prepere color entry in X format. */
00705             XColorTable[i].red = ColorMap->Colors[i].Red << 8;
00706             XColorTable[i].green = ColorMap->Colors[i].Green << 8;
00707             XColorTable[i].blue = ColorMap->Colors[i].Blue << 8;
00708             XColorTable[i].flags = DoRed | DoGreen | DoBlue;
00709             XPixelTable[i] = -1;                       /* Not allocated yet. */
00710         }
00711         else
00712             XPixelTable[i] = 0;    /* Put reasonable color for out of range. */
00713     }
00714 
00715     for (i = 0; i < ColorMapSize; i++)        /* Allocate the colors from X: */
00716         if (XAllocColor(display, colormap, &XColorTable[i]))
00717             XPixelTable[i] = XColorTable[i].pixel;
00718         else
00719             Failed = TRUE;
00720 
00721     if (Failed) {
00722         XNumOfColors = DisplayCells(display, screen);
00723         XOldColorTable = (XColor *) malloc(sizeof(XColor) * XNumOfColors);
00724         for (i = 0; i < XNumOfColors; i++) XOldColorTable[i].pixel = i;
00725         XQueryColors(display, colormap, XOldColorTable, XNumOfColors);
00726 
00727         for (i = 0; i < ColorMapSize; i++) {
00728             /* Allocate closest colors from X: */
00729             if (XPixelTable[i] == -1) {      /* Failed to allocate this one. */
00730                 Distance = 0xffffffff;
00731 
00732                 Red = XColorTable[i].red;
00733                 Green = XColorTable[i].green;
00734                 Blue = XColorTable[i].blue;
00735 
00736                 for (j = 0; j < XNumOfColors; j++) {
00737                     /* Find the closest color in 3D RGB space using L1 norm. */
00738                     if ((D = ABS(Red - XOldColorTable[j].red) +
00739                              ABS(Green - XOldColorTable[j].green) +
00740                              ABS(Blue - XOldColorTable[j].blue)) < Distance) {
00741                         Distance = D;
00742                         Index = j;
00743                     }
00744                 }
00745                 XPixelTable[i] = Index;
00746 
00747                 AvgDistance += Distance;
00748                 Count++;
00749             }
00750         }
00751         free(XOldColorTable);
00752 
00753         sprintf(Msg, "Colors will be approximated (average error = %d).\n",
00754                 AvgDistance / Count);
00755         printf(Msg);
00756     }
00757 }
00758