/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkimgbmap.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkimgbmap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkImgBmap.c --   * tkImgBmap.c --
5   *   *
6   *      This procedure implements images of type "bitmap" for Tk.   *      This procedure implements images of type "bitmap" for Tk.
7   *   *
8   * Copyright (c) 1994 The Regents of the University of California.   * Copyright (c) 1994 The Regents of the University of California.
9   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10   * Copyright (c) 1999 by Scriptics Corporation.   * Copyright (c) 1999 by Scriptics Corporation.
11   *   *
12   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
13   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14   *   *
15   * RCS: @(#) $Id: tkimgbmap.c,v 1.1.1.1 2001/06/13 05:02:24 dtashley Exp $   * RCS: @(#) $Id: tkimgbmap.c,v 1.1.1.1 2001/06/13 05:02:24 dtashley Exp $
16   */   */
17    
18  #include "tkInt.h"  #include "tkInt.h"
19  #include "tkPort.h"  #include "tkPort.h"
20    
21  /*  /*
22   * The following data structure represents the master for a bitmap   * The following data structure represents the master for a bitmap
23   * image:   * image:
24   */   */
25    
26  typedef struct BitmapMaster {  typedef struct BitmapMaster {
27      Tk_ImageMaster tkMaster;    /* Tk's token for image master.  NULL means      Tk_ImageMaster tkMaster;    /* Tk's token for image master.  NULL means
28                                   * the image is being deleted. */                                   * the image is being deleted. */
29      Tcl_Interp *interp;         /* Interpreter for application that is      Tcl_Interp *interp;         /* Interpreter for application that is
30                                   * using image. */                                   * using image. */
31      Tcl_Command imageCmd;       /* Token for image command (used to delete      Tcl_Command imageCmd;       /* Token for image command (used to delete
32                                   * it when the image goes away).  NULL means                                   * it when the image goes away).  NULL means
33                                   * the image command has already been                                   * the image command has already been
34                                   * deleted. */                                   * deleted. */
35      int width, height;          /* Dimensions of image. */      int width, height;          /* Dimensions of image. */
36      char *data;                 /* Data comprising bitmap (suitable for      char *data;                 /* Data comprising bitmap (suitable for
37                                   * input to XCreateBitmapFromData).   May                                   * input to XCreateBitmapFromData).   May
38                                   * be NULL if no data.  Malloc'ed. */                                   * be NULL if no data.  Malloc'ed. */
39      char *maskData;             /* Data for bitmap's mask (suitable for      char *maskData;             /* Data for bitmap's mask (suitable for
40                                   * input to XCreateBitmapFromData).                                   * input to XCreateBitmapFromData).
41                                   * Malloc'ed. */                                   * Malloc'ed. */
42      Tk_Uid fgUid;               /* Value of -foreground option (malloc'ed). */      Tk_Uid fgUid;               /* Value of -foreground option (malloc'ed). */
43      Tk_Uid bgUid;               /* Value of -background option (malloc'ed). */      Tk_Uid bgUid;               /* Value of -background option (malloc'ed). */
44      char *fileString;           /* Value of -file option (malloc'ed). */      char *fileString;           /* Value of -file option (malloc'ed). */
45      char *dataString;           /* Value of -data option (malloc'ed). */      char *dataString;           /* Value of -data option (malloc'ed). */
46      char *maskFileString;       /* Value of -maskfile option (malloc'ed). */      char *maskFileString;       /* Value of -maskfile option (malloc'ed). */
47      char *maskDataString;       /* Value of -maskdata option (malloc'ed). */      char *maskDataString;       /* Value of -maskdata option (malloc'ed). */
48      struct BitmapInstance *instancePtr;      struct BitmapInstance *instancePtr;
49                                  /* First in list of all instances associated                                  /* First in list of all instances associated
50                                   * with this master. */                                   * with this master. */
51  } BitmapMaster;  } BitmapMaster;
52    
53  /*  /*
54   * The following data structure represents all of the instances of an   * The following data structure represents all of the instances of an
55   * image that lie within a particular window:   * image that lie within a particular window:
56   */   */
57    
58  typedef struct BitmapInstance {  typedef struct BitmapInstance {
59      int refCount;               /* Number of instances that share this      int refCount;               /* Number of instances that share this
60                                   * data structure. */                                   * data structure. */
61      BitmapMaster *masterPtr;    /* Pointer to master for image. */      BitmapMaster *masterPtr;    /* Pointer to master for image. */
62      Tk_Window tkwin;            /* Window in which the instances will be      Tk_Window tkwin;            /* Window in which the instances will be
63                                   * displayed. */                                   * displayed. */
64      XColor *fg;                 /* Foreground color for displaying image. */      XColor *fg;                 /* Foreground color for displaying image. */
65      XColor *bg;                 /* Background color for displaying image. */      XColor *bg;                 /* Background color for displaying image. */
66      Pixmap bitmap;              /* The bitmap to display. */      Pixmap bitmap;              /* The bitmap to display. */
67      Pixmap mask;                /* Mask: only display bitmap pixels where      Pixmap mask;                /* Mask: only display bitmap pixels where
68                                   * there are 1's here. */                                   * there are 1's here. */
69      GC gc;                      /* Graphics context for displaying bitmap.      GC gc;                      /* Graphics context for displaying bitmap.
70                                   * None means there was an error while                                   * None means there was an error while
71                                   * setting up the instance, so it cannot                                   * setting up the instance, so it cannot
72                                   * be displayed. */                                   * be displayed. */
73      struct BitmapInstance *nextPtr;      struct BitmapInstance *nextPtr;
74                                  /* Next in list of all instance structures                                  /* Next in list of all instance structures
75                                   * associated with masterPtr (NULL means                                   * associated with masterPtr (NULL means
76                                   * end of list). */                                   * end of list). */
77  } BitmapInstance;  } BitmapInstance;
78    
79  /*  /*
80   * The type record for bitmap images:   * The type record for bitmap images:
81   */   */
82    
83  static int              GetByte _ANSI_ARGS_((Tcl_Channel chan));  static int              GetByte _ANSI_ARGS_((Tcl_Channel chan));
84  static int              ImgBmapCreate _ANSI_ARGS_((Tcl_Interp *interp,  static int              ImgBmapCreate _ANSI_ARGS_((Tcl_Interp *interp,
85                              char *name, int argc, Tcl_Obj *CONST objv[],                              char *name, int argc, Tcl_Obj *CONST objv[],
86                              Tk_ImageType *typePtr, Tk_ImageMaster master,                              Tk_ImageType *typePtr, Tk_ImageMaster master,
87                              ClientData *clientDataPtr));                              ClientData *clientDataPtr));
88  static ClientData       ImgBmapGet _ANSI_ARGS_((Tk_Window tkwin,  static ClientData       ImgBmapGet _ANSI_ARGS_((Tk_Window tkwin,
89                              ClientData clientData));                              ClientData clientData));
90  static void             ImgBmapDisplay _ANSI_ARGS_((ClientData clientData,  static void             ImgBmapDisplay _ANSI_ARGS_((ClientData clientData,
91                              Display *display, Drawable drawable,                              Display *display, Drawable drawable,
92                              int imageX, int imageY, int width, int height,                              int imageX, int imageY, int width, int height,
93                              int drawableX, int drawableY));                              int drawableX, int drawableY));
94  static void             ImgBmapFree _ANSI_ARGS_((ClientData clientData,  static void             ImgBmapFree _ANSI_ARGS_((ClientData clientData,
95                              Display *display));                              Display *display));
96  static void             ImgBmapDelete _ANSI_ARGS_((ClientData clientData));  static void             ImgBmapDelete _ANSI_ARGS_((ClientData clientData));
97  static int              ImgBmapPostscript _ANSI_ARGS_((ClientData clientData,  static int              ImgBmapPostscript _ANSI_ARGS_((ClientData clientData,
98                              Tcl_Interp *interp, Tk_Window tkwin,                              Tcl_Interp *interp, Tk_Window tkwin,
99                              Tk_PostscriptInfo psinfo, int x, int y,                              Tk_PostscriptInfo psinfo, int x, int y,
100                              int width, int height, int prepass));                              int width, int height, int prepass));
101    
102  Tk_ImageType tkBitmapImageType = {  Tk_ImageType tkBitmapImageType = {
103      "bitmap",                   /* name */      "bitmap",                   /* name */
104      ImgBmapCreate,              /* createProc */      ImgBmapCreate,              /* createProc */
105      ImgBmapGet,                 /* getProc */      ImgBmapGet,                 /* getProc */
106      ImgBmapDisplay,             /* displayProc */      ImgBmapDisplay,             /* displayProc */
107      ImgBmapFree,                /* freeProc */      ImgBmapFree,                /* freeProc */
108      ImgBmapDelete,              /* deleteProc */      ImgBmapDelete,              /* deleteProc */
109      ImgBmapPostscript,          /* postscriptProc */      ImgBmapPostscript,          /* postscriptProc */
110      (Tk_ImageType *) NULL       /* nextPtr */      (Tk_ImageType *) NULL       /* nextPtr */
111  };  };
112    
113  /*  /*
114   * Information used for parsing configuration specs:   * Information used for parsing configuration specs:
115   */   */
116    
117  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
118      {TK_CONFIG_UID, "-background", (char *) NULL, (char *) NULL,      {TK_CONFIG_UID, "-background", (char *) NULL, (char *) NULL,
119          "", Tk_Offset(BitmapMaster, bgUid), 0},          "", Tk_Offset(BitmapMaster, bgUid), 0},
120      {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL,
121          (char *) NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK},
122      {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
123          (char *) NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK},          (char *) NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK},
124      {TK_CONFIG_UID, "-foreground", (char *) NULL, (char *) NULL,      {TK_CONFIG_UID, "-foreground", (char *) NULL, (char *) NULL,
125          "#000000", Tk_Offset(BitmapMaster, fgUid), 0},          "#000000", Tk_Offset(BitmapMaster, fgUid), 0},
126      {TK_CONFIG_STRING, "-maskdata", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-maskdata", (char *) NULL, (char *) NULL,
127          (char *) NULL, Tk_Offset(BitmapMaster, maskDataString),          (char *) NULL, Tk_Offset(BitmapMaster, maskDataString),
128          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
129      {TK_CONFIG_STRING, "-maskfile", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-maskfile", (char *) NULL, (char *) NULL,
130          (char *) NULL, Tk_Offset(BitmapMaster, maskFileString),          (char *) NULL, Tk_Offset(BitmapMaster, maskFileString),
131          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
132      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
133          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
134  };  };
135    
136  /*  /*
137   * The following data structure is used to describe the state of   * The following data structure is used to describe the state of
138   * parsing a bitmap file or string.  It is used for communication   * parsing a bitmap file or string.  It is used for communication
139   * between TkGetBitmapData and NextBitmapWord.   * between TkGetBitmapData and NextBitmapWord.
140   */   */
141    
142  #define MAX_WORD_LENGTH 100  #define MAX_WORD_LENGTH 100
143  typedef struct ParseInfo {  typedef struct ParseInfo {
144      char *string;               /* Next character of string data for bitmap,      char *string;               /* Next character of string data for bitmap,
145                                   * or NULL if bitmap is being read from                                   * or NULL if bitmap is being read from
146                                   * file. */                                   * file. */
147      Tcl_Channel chan;           /* File containing bitmap data, or NULL      Tcl_Channel chan;           /* File containing bitmap data, or NULL
148                                   * if no file. */                                   * if no file. */
149      char word[MAX_WORD_LENGTH+1];      char word[MAX_WORD_LENGTH+1];
150                                  /* Current word of bitmap data, NULL                                  /* Current word of bitmap data, NULL
151                                   * terminated. */                                   * terminated. */
152      int wordLength;             /* Number of non-NULL bytes in word. */      int wordLength;             /* Number of non-NULL bytes in word. */
153  } ParseInfo;  } ParseInfo;
154    
155  /*  /*
156   * Prototypes for procedures used only locally in this file:   * Prototypes for procedures used only locally in this file:
157   */   */
158    
159  static int              ImgBmapCmd _ANSI_ARGS_((ClientData clientData,  static int              ImgBmapCmd _ANSI_ARGS_((ClientData clientData,
160                              Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));                              Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
161  static void             ImgBmapCmdDeletedProc _ANSI_ARGS_((  static void             ImgBmapCmdDeletedProc _ANSI_ARGS_((
162                              ClientData clientData));                              ClientData clientData));
163  static void             ImgBmapConfigureInstance _ANSI_ARGS_((  static void             ImgBmapConfigureInstance _ANSI_ARGS_((
164                              BitmapInstance *instancePtr));                              BitmapInstance *instancePtr));
165  static int              ImgBmapConfigureMaster _ANSI_ARGS_((  static int              ImgBmapConfigureMaster _ANSI_ARGS_((
166                              BitmapMaster *masterPtr, int argc, Tcl_Obj *CONST objv[],                              BitmapMaster *masterPtr, int argc, Tcl_Obj *CONST objv[],
167                              int flags));                              int flags));
168  static int              NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr));  static int              NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr));
169    
170  /*  /*
171   *----------------------------------------------------------------------   *----------------------------------------------------------------------
172   *   *
173   * ImgBmapCreate --   * ImgBmapCreate --
174   *   *
175   *      This procedure is called by the Tk image code to create "test"   *      This procedure is called by the Tk image code to create "test"
176   *      images.   *      images.
177   *   *
178   * Results:   * Results:
179   *      A standard Tcl result.   *      A standard Tcl result.
180   *   *
181   * Side effects:   * Side effects:
182   *      The data structure for a new image is allocated.   *      The data structure for a new image is allocated.
183   *   *
184   *----------------------------------------------------------------------   *----------------------------------------------------------------------
185   */   */
186    
187          /* ARGSUSED */          /* ARGSUSED */
188  static int  static int
189  ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)  ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
190      Tcl_Interp *interp;         /* Interpreter for application containing      Tcl_Interp *interp;         /* Interpreter for application containing
191                                   * image. */                                   * image. */
192      char *name;                 /* Name to use for image. */      char *name;                 /* Name to use for image. */
193      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
194      Tcl_Obj *CONST argv[];      /* Argument objects for options (doesn't      Tcl_Obj *CONST argv[];      /* Argument objects for options (doesn't
195                                   * include image name or type). */                                   * include image name or type). */
196      Tk_ImageType *typePtr;      /* Pointer to our type record (not used). */      Tk_ImageType *typePtr;      /* Pointer to our type record (not used). */
197      Tk_ImageMaster master;      /* Token for image, to be used by us in      Tk_ImageMaster master;      /* Token for image, to be used by us in
198                                   * later callbacks. */                                   * later callbacks. */
199      ClientData *clientDataPtr;  /* Store manager's token for image here;      ClientData *clientDataPtr;  /* Store manager's token for image here;
200                                   * it will be returned in later callbacks. */                                   * it will be returned in later callbacks. */
201  {  {
202      BitmapMaster *masterPtr;      BitmapMaster *masterPtr;
203    
204      masterPtr = (BitmapMaster *) ckalloc(sizeof(BitmapMaster));      masterPtr = (BitmapMaster *) ckalloc(sizeof(BitmapMaster));
205      masterPtr->tkMaster = master;      masterPtr->tkMaster = master;
206      masterPtr->interp = interp;      masterPtr->interp = interp;
207      masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,      masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,
208              (ClientData) masterPtr, ImgBmapCmdDeletedProc);              (ClientData) masterPtr, ImgBmapCmdDeletedProc);
209      masterPtr->width = masterPtr->height = 0;      masterPtr->width = masterPtr->height = 0;
210      masterPtr->data = NULL;      masterPtr->data = NULL;
211      masterPtr->maskData = NULL;      masterPtr->maskData = NULL;
212      masterPtr->fgUid = NULL;      masterPtr->fgUid = NULL;
213      masterPtr->bgUid = NULL;      masterPtr->bgUid = NULL;
214      masterPtr->fileString = NULL;      masterPtr->fileString = NULL;
215      masterPtr->dataString = NULL;      masterPtr->dataString = NULL;
216      masterPtr->maskFileString = NULL;      masterPtr->maskFileString = NULL;
217      masterPtr->maskDataString = NULL;      masterPtr->maskDataString = NULL;
218      masterPtr->instancePtr = NULL;      masterPtr->instancePtr = NULL;
219      if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {      if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
220          ImgBmapDelete((ClientData) masterPtr);          ImgBmapDelete((ClientData) masterPtr);
221          return TCL_ERROR;          return TCL_ERROR;
222      }      }
223      *clientDataPtr = (ClientData) masterPtr;      *clientDataPtr = (ClientData) masterPtr;
224      return TCL_OK;      return TCL_OK;
225  }  }
226    
227  /*  /*
228   *----------------------------------------------------------------------   *----------------------------------------------------------------------
229   *   *
230   * ImgBmapConfigureMaster --   * ImgBmapConfigureMaster --
231   *   *
232   *      This procedure is called when a bitmap image is created or   *      This procedure is called when a bitmap image is created or
233   *      reconfigured.  It process configuration options and resets   *      reconfigured.  It process configuration options and resets
234   *      any instances of the image.   *      any instances of the image.
235   *   *
236   * Results:   * Results:
237   *      A standard Tcl return value.  If TCL_ERROR is returned then   *      A standard Tcl return value.  If TCL_ERROR is returned then
238   *      an error message is left in the masterPtr->interp's result.   *      an error message is left in the masterPtr->interp's result.
239   *   *
240   * Side effects:   * Side effects:
241   *      Existing instances of the image will be redisplayed to match   *      Existing instances of the image will be redisplayed to match
242   *      the new configuration options.   *      the new configuration options.
243   *   *
244   *----------------------------------------------------------------------   *----------------------------------------------------------------------
245   */   */
246    
247  static int  static int
248  ImgBmapConfigureMaster(masterPtr, objc, objv, flags)  ImgBmapConfigureMaster(masterPtr, objc, objv, flags)
249      BitmapMaster *masterPtr;    /* Pointer to data structure describing      BitmapMaster *masterPtr;    /* Pointer to data structure describing
250                                   * overall bitmap image to (reconfigure). */                                   * overall bitmap image to (reconfigure). */
251      int objc;                   /* Number of entries in objv. */      int objc;                   /* Number of entries in objv. */
252      Tcl_Obj *CONST objv[];      /* Pairs of configuration options for image. */      Tcl_Obj *CONST objv[];      /* Pairs of configuration options for image. */
253      int flags;                  /* Flags to pass to Tk_ConfigureWidget,      int flags;                  /* Flags to pass to Tk_ConfigureWidget,
254                                   * such as TK_CONFIG_ARGV_ONLY. */                                   * such as TK_CONFIG_ARGV_ONLY. */
255  {  {
256      BitmapInstance *instancePtr;      BitmapInstance *instancePtr;
257      int maskWidth, maskHeight, dummy1, dummy2;      int maskWidth, maskHeight, dummy1, dummy2;
258    
259      char **argv = (char **) ckalloc((objc+1) * sizeof(char *));      char **argv = (char **) ckalloc((objc+1) * sizeof(char *));
260      for (dummy1 = 0; dummy1 < objc; dummy1++) {      for (dummy1 = 0; dummy1 < objc; dummy1++) {
261          argv[dummy1]=Tcl_GetString(objv[dummy1]);          argv[dummy1]=Tcl_GetString(objv[dummy1]);
262      }      }
263      argv[objc] = NULL;      argv[objc] = NULL;
264    
265      if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),      if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
266              configSpecs, objc, argv, (char *) masterPtr, flags)              configSpecs, objc, argv, (char *) masterPtr, flags)
267              != TCL_OK) {              != TCL_OK) {
268          ckfree((char *) argv);          ckfree((char *) argv);
269          return TCL_ERROR;          return TCL_ERROR;
270      }      }
271      ckfree((char *) argv);      ckfree((char *) argv);
272    
273      /*      /*
274       * Parse the bitmap and/or mask to create binary data.  Make sure that       * Parse the bitmap and/or mask to create binary data.  Make sure that
275       * the bitmap and mask have the same dimensions.       * the bitmap and mask have the same dimensions.
276       */       */
277    
278      if (masterPtr->data != NULL) {      if (masterPtr->data != NULL) {
279          ckfree(masterPtr->data);          ckfree(masterPtr->data);
280          masterPtr->data = NULL;          masterPtr->data = NULL;
281      }      }
282      if ((masterPtr->fileString != NULL) || (masterPtr->dataString != NULL)) {      if ((masterPtr->fileString != NULL) || (masterPtr->dataString != NULL)) {
283          masterPtr->data = TkGetBitmapData(masterPtr->interp,          masterPtr->data = TkGetBitmapData(masterPtr->interp,
284                  masterPtr->dataString, masterPtr->fileString,                  masterPtr->dataString, masterPtr->fileString,
285                  &masterPtr->width, &masterPtr->height, &dummy1, &dummy2);                  &masterPtr->width, &masterPtr->height, &dummy1, &dummy2);
286          if (masterPtr->data == NULL) {          if (masterPtr->data == NULL) {
287              return TCL_ERROR;              return TCL_ERROR;
288          }          }
289      }      }
290      if (masterPtr->maskData != NULL) {      if (masterPtr->maskData != NULL) {
291          ckfree(masterPtr->maskData);          ckfree(masterPtr->maskData);
292          masterPtr->maskData = NULL;          masterPtr->maskData = NULL;
293      }      }
294      if ((masterPtr->maskFileString != NULL)      if ((masterPtr->maskFileString != NULL)
295              || (masterPtr->maskDataString != NULL)) {              || (masterPtr->maskDataString != NULL)) {
296          if (masterPtr->data == NULL) {          if (masterPtr->data == NULL) {
297              Tcl_SetResult(masterPtr->interp, "can't have mask without bitmap",              Tcl_SetResult(masterPtr->interp, "can't have mask without bitmap",
298                      TCL_STATIC);                      TCL_STATIC);
299              return TCL_ERROR;              return TCL_ERROR;
300          }          }
301          masterPtr->maskData = TkGetBitmapData(masterPtr->interp,          masterPtr->maskData = TkGetBitmapData(masterPtr->interp,
302                  masterPtr->maskDataString, masterPtr->maskFileString,                  masterPtr->maskDataString, masterPtr->maskFileString,
303                  &maskWidth, &maskHeight, &dummy1, &dummy2);                  &maskWidth, &maskHeight, &dummy1, &dummy2);
304          if (masterPtr->maskData == NULL) {          if (masterPtr->maskData == NULL) {
305              return TCL_ERROR;              return TCL_ERROR;
306          }          }
307          if ((maskWidth != masterPtr->width)          if ((maskWidth != masterPtr->width)
308                  || (maskHeight != masterPtr->height)) {                  || (maskHeight != masterPtr->height)) {
309              ckfree(masterPtr->maskData);              ckfree(masterPtr->maskData);
310              masterPtr->maskData = NULL;              masterPtr->maskData = NULL;
311              Tcl_SetResult(masterPtr->interp,              Tcl_SetResult(masterPtr->interp,
312                      "bitmap and mask have different sizes", TCL_STATIC);                      "bitmap and mask have different sizes", TCL_STATIC);
313              return TCL_ERROR;              return TCL_ERROR;
314          }          }
315      }      }
316    
317      /*      /*
318       * Cycle through all of the instances of this image, regenerating       * Cycle through all of the instances of this image, regenerating
319       * the information for each instance.  Then force the image to be       * the information for each instance.  Then force the image to be
320       * redisplayed everywhere that it is used.       * redisplayed everywhere that it is used.
321       */       */
322    
323      for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;      for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
324              instancePtr = instancePtr->nextPtr) {              instancePtr = instancePtr->nextPtr) {
325          ImgBmapConfigureInstance(instancePtr);          ImgBmapConfigureInstance(instancePtr);
326      }      }
327      Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,      Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
328              masterPtr->height, masterPtr->width, masterPtr->height);              masterPtr->height, masterPtr->width, masterPtr->height);
329      return TCL_OK;      return TCL_OK;
330  }  }
331    
332  /*  /*
333   *----------------------------------------------------------------------   *----------------------------------------------------------------------
334   *   *
335   * ImgBmapConfigureInstance --   * ImgBmapConfigureInstance --
336   *   *
337   *      This procedure is called to create displaying information for   *      This procedure is called to create displaying information for
338   *      a bitmap image instance based on the configuration information   *      a bitmap image instance based on the configuration information
339   *      in the master.  It is invoked both when new instances are   *      in the master.  It is invoked both when new instances are
340   *      created and when the master is reconfigured.   *      created and when the master is reconfigured.
341   *   *
342   * Results:   * Results:
343   *      None.   *      None.
344   *   *
345   * Side effects:   * Side effects:
346   *      Generates errors via Tcl_BackgroundError if there are problems   *      Generates errors via Tcl_BackgroundError if there are problems
347   *      in setting up the instance.   *      in setting up the instance.
348   *   *
349   *----------------------------------------------------------------------   *----------------------------------------------------------------------
350   */   */
351    
352  static void  static void
353  ImgBmapConfigureInstance(instancePtr)  ImgBmapConfigureInstance(instancePtr)
354      BitmapInstance *instancePtr;        /* Instance to reconfigure. */      BitmapInstance *instancePtr;        /* Instance to reconfigure. */
355  {  {
356      BitmapMaster *masterPtr = instancePtr->masterPtr;      BitmapMaster *masterPtr = instancePtr->masterPtr;
357      XColor *colorPtr;      XColor *colorPtr;
358      XGCValues gcValues;      XGCValues gcValues;
359      GC gc;      GC gc;
360      unsigned int mask;      unsigned int mask;
361      Pixmap oldMask;      Pixmap oldMask;
362    
363      /*      /*
364       * For each of the options in masterPtr, translate the string       * For each of the options in masterPtr, translate the string
365       * form into an internal form appropriate for instancePtr.       * form into an internal form appropriate for instancePtr.
366       */       */
367    
368      if (*masterPtr->bgUid != 0) {      if (*masterPtr->bgUid != 0) {
369          colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,          colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
370                  masterPtr->bgUid);                  masterPtr->bgUid);
371          if (colorPtr == NULL) {          if (colorPtr == NULL) {
372              goto error;              goto error;
373          }          }
374      } else {      } else {
375          colorPtr = NULL;          colorPtr = NULL;
376      }      }
377      if (instancePtr->bg != NULL) {      if (instancePtr->bg != NULL) {
378          Tk_FreeColor(instancePtr->bg);          Tk_FreeColor(instancePtr->bg);
379      }      }
380      instancePtr->bg = colorPtr;      instancePtr->bg = colorPtr;
381    
382      colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,      colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
383              masterPtr->fgUid);              masterPtr->fgUid);
384      if (colorPtr == NULL) {      if (colorPtr == NULL) {
385          goto error;          goto error;
386      }      }
387      if (instancePtr->fg != NULL) {      if (instancePtr->fg != NULL) {
388          Tk_FreeColor(instancePtr->fg);          Tk_FreeColor(instancePtr->fg);
389      }      }
390      instancePtr->fg = colorPtr;      instancePtr->fg = colorPtr;
391    
392      if (instancePtr->bitmap != None) {      if (instancePtr->bitmap != None) {
393          Tk_FreePixmap(Tk_Display(instancePtr->tkwin), instancePtr->bitmap);          Tk_FreePixmap(Tk_Display(instancePtr->tkwin), instancePtr->bitmap);
394          instancePtr->bitmap = None;          instancePtr->bitmap = None;
395      }      }
396      if (masterPtr->data != NULL) {      if (masterPtr->data != NULL) {
397          instancePtr->bitmap = XCreateBitmapFromData(          instancePtr->bitmap = XCreateBitmapFromData(
398                  Tk_Display(instancePtr->tkwin),                  Tk_Display(instancePtr->tkwin),
399                  RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),                  RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
400                  masterPtr->data, (unsigned) masterPtr->width,                  masterPtr->data, (unsigned) masterPtr->width,
401                  (unsigned) masterPtr->height);                  (unsigned) masterPtr->height);
402      }      }
403    
404      /*      /*
405       * Careful:  We have to allocate a new mask Pixmap before deleting       * Careful:  We have to allocate a new mask Pixmap before deleting
406       * the old one.  Otherwise, The XID allocator will always return       * the old one.  Otherwise, The XID allocator will always return
407       * the same XID for the new Pixmap as was used for the old Pixmap.       * the same XID for the new Pixmap as was used for the old Pixmap.
408       * And that will prevent the mask from changing in the GC below.       * And that will prevent the mask from changing in the GC below.
409       */       */
410      oldMask = instancePtr->mask;      oldMask = instancePtr->mask;
411      instancePtr->mask = None;      instancePtr->mask = None;
412      if (masterPtr->maskData != NULL) {      if (masterPtr->maskData != NULL) {
413          instancePtr->mask = XCreateBitmapFromData(          instancePtr->mask = XCreateBitmapFromData(
414                  Tk_Display(instancePtr->tkwin),                  Tk_Display(instancePtr->tkwin),
415                  RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),                  RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
416                  masterPtr->maskData, (unsigned) masterPtr->width,                  masterPtr->maskData, (unsigned) masterPtr->width,
417                  (unsigned) masterPtr->height);                  (unsigned) masterPtr->height);
418      }      }
419      if (oldMask != None) {      if (oldMask != None) {
420        Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);        Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);
421      }      }
422    
423      if (masterPtr->data != NULL) {      if (masterPtr->data != NULL) {
424          gcValues.foreground = instancePtr->fg->pixel;          gcValues.foreground = instancePtr->fg->pixel;
425          gcValues.graphics_exposures = False;          gcValues.graphics_exposures = False;
426          mask = GCForeground|GCGraphicsExposures;          mask = GCForeground|GCGraphicsExposures;
427          if (instancePtr->bg != NULL) {          if (instancePtr->bg != NULL) {
428              gcValues.background = instancePtr->bg->pixel;              gcValues.background = instancePtr->bg->pixel;
429              mask |= GCBackground;              mask |= GCBackground;
430              if (instancePtr->mask != None) {              if (instancePtr->mask != None) {
431                  gcValues.clip_mask = instancePtr->mask;                  gcValues.clip_mask = instancePtr->mask;
432                  mask |= GCClipMask;                  mask |= GCClipMask;
433              }              }
434          } else {          } else {
435              gcValues.clip_mask = instancePtr->bitmap;              gcValues.clip_mask = instancePtr->bitmap;
436              mask |= GCClipMask;              mask |= GCClipMask;
437          }          }
438          gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);          gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);
439      } else {      } else {
440          gc = None;          gc = None;
441      }      }
442      if (instancePtr->gc != None) {      if (instancePtr->gc != None) {
443          Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);          Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
444      }      }
445      instancePtr->gc = gc;      instancePtr->gc = gc;
446      return;      return;
447    
448      error:      error:
449      /*      /*
450       * An error occurred: clear the graphics context in the instance to       * An error occurred: clear the graphics context in the instance to
451       * make it clear that this instance cannot be displayed.  Then report       * make it clear that this instance cannot be displayed.  Then report
452       * the error.       * the error.
453       */       */
454    
455      if (instancePtr->gc != None) {      if (instancePtr->gc != None) {
456          Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);          Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
457      }      }
458      instancePtr->gc = None;      instancePtr->gc = None;
459      Tcl_AddErrorInfo(masterPtr->interp, "\n    (while configuring image \"");      Tcl_AddErrorInfo(masterPtr->interp, "\n    (while configuring image \"");
460      Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));      Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
461      Tcl_AddErrorInfo(masterPtr->interp, "\")");      Tcl_AddErrorInfo(masterPtr->interp, "\")");
462      Tcl_BackgroundError(masterPtr->interp);      Tcl_BackgroundError(masterPtr->interp);
463  }  }
464    
465  /*  /*
466   *----------------------------------------------------------------------   *----------------------------------------------------------------------
467   *   *
468   * TkGetBitmapData --   * TkGetBitmapData --
469   *   *
470   *      Given a file name or ASCII string, this procedure parses the   *      Given a file name or ASCII string, this procedure parses the
471   *      file or string contents to produce binary data for a bitmap.   *      file or string contents to produce binary data for a bitmap.
472   *   *
473   * Results:   * Results:
474   *      If the bitmap description was parsed successfully then the   *      If the bitmap description was parsed successfully then the
475   *      return value is a malloc-ed array containing the bitmap data.   *      return value is a malloc-ed array containing the bitmap data.
476   *      The dimensions of the data are stored in *widthPtr and   *      The dimensions of the data are stored in *widthPtr and
477   *      *heightPtr.  *hotXPtr and *hotYPtr are set to the bitmap   *      *heightPtr.  *hotXPtr and *hotYPtr are set to the bitmap
478   *      hotspot if one is defined, otherwise they are set to -1, -1.   *      hotspot if one is defined, otherwise they are set to -1, -1.
479   *      If an error occurred, NULL is returned and an error message is   *      If an error occurred, NULL is returned and an error message is
480   *      left in the interp's result.   *      left in the interp's result.
481   *   *
482   * Side effects:   * Side effects:
483   *      A bitmap is created.   *      A bitmap is created.
484   *   *
485   *----------------------------------------------------------------------   *----------------------------------------------------------------------
486   */   */
487    
488  char *  char *
489  TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr,  TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr,
490          hotXPtr, hotYPtr)          hotXPtr, hotYPtr)
491      Tcl_Interp *interp;                 /* For reporting errors, or NULL. */      Tcl_Interp *interp;                 /* For reporting errors, or NULL. */
492      char *string;                       /* String describing bitmap.  May      char *string;                       /* String describing bitmap.  May
493                                           * be NULL. */                                           * be NULL. */
494      char *fileName;                     /* Name of file containing bitmap      char *fileName;                     /* Name of file containing bitmap
495                                           * description.  Used only if string                                           * description.  Used only if string
496                                           * is NULL.  Must not be NULL if                                           * is NULL.  Must not be NULL if
497                                           * string is NULL. */                                           * string is NULL. */
498      int *widthPtr, *heightPtr;          /* Dimensions of bitmap get returned      int *widthPtr, *heightPtr;          /* Dimensions of bitmap get returned
499                                           * here. */                                           * here. */
500      int *hotXPtr, *hotYPtr;             /* Position of hot spot or -1,-1. */      int *hotXPtr, *hotYPtr;             /* Position of hot spot or -1,-1. */
501  {  {
502      int width, height, numBytes, hotX, hotY;      int width, height, numBytes, hotX, hotY;
503      char *p, *end, *expandedFileName;      char *p, *end, *expandedFileName;
504      ParseInfo pi;      ParseInfo pi;
505      char *data = NULL;      char *data = NULL;
506      Tcl_DString buffer;      Tcl_DString buffer;
507    
508      pi.string = string;      pi.string = string;
509      if (string == NULL) {      if (string == NULL) {
510          if ((interp != NULL) && Tcl_IsSafe(interp)) {          if ((interp != NULL) && Tcl_IsSafe(interp)) {
511              Tcl_AppendResult(interp, "can't get bitmap data from a file in a",              Tcl_AppendResult(interp, "can't get bitmap data from a file in a",
512                      " safe interpreter", (char *) NULL);                      " safe interpreter", (char *) NULL);
513              return NULL;              return NULL;
514          }          }
515          expandedFileName = Tcl_TranslateFileName(interp, fileName, &buffer);          expandedFileName = Tcl_TranslateFileName(interp, fileName, &buffer);
516          if (expandedFileName == NULL) {          if (expandedFileName == NULL) {
517              return NULL;              return NULL;
518          }          }
519          pi.chan = Tcl_OpenFileChannel(interp, expandedFileName, "r", 0);          pi.chan = Tcl_OpenFileChannel(interp, expandedFileName, "r", 0);
520          Tcl_DStringFree(&buffer);          Tcl_DStringFree(&buffer);
521          if (pi.chan == NULL) {          if (pi.chan == NULL) {
522              if (interp != NULL) {              if (interp != NULL) {
523                  Tcl_ResetResult(interp);                  Tcl_ResetResult(interp);
524                  Tcl_AppendResult(interp, "couldn't read bitmap file \"",                  Tcl_AppendResult(interp, "couldn't read bitmap file \"",
525                          fileName, "\": ", Tcl_PosixError(interp),                          fileName, "\": ", Tcl_PosixError(interp),
526                          (char *) NULL);                          (char *) NULL);
527              }              }
528              return NULL;              return NULL;
529          }          }
530                    
531          if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary")          if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary")
532                  != TCL_OK) {                  != TCL_OK) {
533              return NULL;              return NULL;
534          }          }
535          if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary")          if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary")
536                  != TCL_OK) {                  != TCL_OK) {
537              return NULL;              return NULL;
538          }          }
539      } else {      } else {
540          pi.chan = NULL;          pi.chan = NULL;
541      }      }
542    
543      /*      /*
544       * Parse the lines that define the dimensions of the bitmap,       * Parse the lines that define the dimensions of the bitmap,
545       * plus the first line that defines the bitmap data (it declares       * plus the first line that defines the bitmap data (it declares
546       * the name of a data variable but doesn't include any actual       * the name of a data variable but doesn't include any actual
547       * data).  These lines look something like the following:       * data).  These lines look something like the following:
548       *       *
549       *          #define foo_width 16       *          #define foo_width 16
550       *          #define foo_height 16       *          #define foo_height 16
551       *          #define foo_x_hot 3       *          #define foo_x_hot 3
552       *          #define foo_y_hot 3       *          #define foo_y_hot 3
553       *          static char foo_bits[] = {       *          static char foo_bits[] = {
554       *       *
555       * The x_hot and y_hot lines may or may not be present.  It's       * The x_hot and y_hot lines may or may not be present.  It's
556       * important to check for "char" in the last line, in order to       * important to check for "char" in the last line, in order to
557       * reject old X10-style bitmaps that used shorts.       * reject old X10-style bitmaps that used shorts.
558       */       */
559    
560      width = 0;      width = 0;
561      height = 0;      height = 0;
562      hotX = -1;      hotX = -1;
563      hotY = -1;      hotY = -1;
564      while (1) {      while (1) {
565          if (NextBitmapWord(&pi) != TCL_OK) {          if (NextBitmapWord(&pi) != TCL_OK) {
566              goto error;              goto error;
567          }          }
568          if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')          if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
569                  && (strcmp(pi.word+pi.wordLength-6, "_width") == 0)) {                  && (strcmp(pi.word+pi.wordLength-6, "_width") == 0)) {
570              if (NextBitmapWord(&pi) != TCL_OK) {              if (NextBitmapWord(&pi) != TCL_OK) {
571                  goto error;                  goto error;
572              }              }
573              width = strtol(pi.word, &end, 0);              width = strtol(pi.word, &end, 0);
574              if ((end == pi.word) || (*end != 0)) {              if ((end == pi.word) || (*end != 0)) {
575                  goto error;                  goto error;
576              }              }
577          } else if ((pi.wordLength >= 7) && (pi.word[pi.wordLength-7] == '_')          } else if ((pi.wordLength >= 7) && (pi.word[pi.wordLength-7] == '_')
578                  && (strcmp(pi.word+pi.wordLength-7, "_height") == 0)) {                  && (strcmp(pi.word+pi.wordLength-7, "_height") == 0)) {
579              if (NextBitmapWord(&pi) != TCL_OK) {              if (NextBitmapWord(&pi) != TCL_OK) {
580                  goto error;                  goto error;
581              }              }
582              height = strtol(pi.word, &end, 0);              height = strtol(pi.word, &end, 0);
583              if ((end == pi.word) || (*end != 0)) {              if ((end == pi.word) || (*end != 0)) {
584                  goto error;                  goto error;
585              }              }
586          } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')          } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
587                  && (strcmp(pi.word+pi.wordLength-6, "_x_hot") == 0)) {                  && (strcmp(pi.word+pi.wordLength-6, "_x_hot") == 0)) {
588              if (NextBitmapWord(&pi) != TCL_OK) {              if (NextBitmapWord(&pi) != TCL_OK) {
589                  goto error;                  goto error;
590              }              }
591              hotX = strtol(pi.word, &end, 0);              hotX = strtol(pi.word, &end, 0);
592              if ((end == pi.word) || (*end != 0)) {              if ((end == pi.word) || (*end != 0)) {
593                  goto error;                  goto error;
594              }              }
595          } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')          } else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')
596                  && (strcmp(pi.word+pi.wordLength-6, "_y_hot") == 0)) {                  && (strcmp(pi.word+pi.wordLength-6, "_y_hot") == 0)) {
597              if (NextBitmapWord(&pi) != TCL_OK) {              if (NextBitmapWord(&pi) != TCL_OK) {
598                  goto error;                  goto error;
599              }              }
600              hotY = strtol(pi.word, &end, 0);              hotY = strtol(pi.word, &end, 0);
601              if ((end == pi.word) || (*end != 0)) {              if ((end == pi.word) || (*end != 0)) {
602                  goto error;                  goto error;
603              }              }
604          } else if ((pi.word[0] == 'c') && (strcmp(pi.word, "char") == 0)) {          } else if ((pi.word[0] == 'c') && (strcmp(pi.word, "char") == 0)) {
605              while (1) {              while (1) {
606                  if (NextBitmapWord(&pi) != TCL_OK) {                  if (NextBitmapWord(&pi) != TCL_OK) {
607                      goto error;                      goto error;
608                  }                  }
609                  if ((pi.word[0] == '{') && (pi.word[1] == 0)) {                  if ((pi.word[0] == '{') && (pi.word[1] == 0)) {
610                      goto getData;                      goto getData;
611                  }                  }
612              }              }
613          } else if ((pi.word[0] == '{') && (pi.word[1] == 0)) {          } else if ((pi.word[0] == '{') && (pi.word[1] == 0)) {
614              if (interp != NULL) {              if (interp != NULL) {
615                  Tcl_AppendResult(interp, "format error in bitmap data; ",                  Tcl_AppendResult(interp, "format error in bitmap data; ",
616                          "looks like it's an obsolete X10 bitmap file",                          "looks like it's an obsolete X10 bitmap file",
617                          (char *) NULL);                          (char *) NULL);
618              }              }
619              goto errorCleanup;              goto errorCleanup;
620          }          }
621      }      }
622    
623      /*      /*
624       * Now we've read everything but the data.  Allocate an array       * Now we've read everything but the data.  Allocate an array
625       * and read in the data.       * and read in the data.
626       */       */
627    
628      getData:      getData:
629      if ((width <= 0) || (height <= 0)) {      if ((width <= 0) || (height <= 0)) {
630          goto error;          goto error;
631      }      }
632      numBytes = ((width+7)/8) * height;      numBytes = ((width+7)/8) * height;
633      data = (char *) ckalloc((unsigned) numBytes);      data = (char *) ckalloc((unsigned) numBytes);
634      for (p = data; numBytes > 0; p++, numBytes--) {      for (p = data; numBytes > 0; p++, numBytes--) {
635          if (NextBitmapWord(&pi) != TCL_OK) {          if (NextBitmapWord(&pi) != TCL_OK) {
636              goto error;              goto error;
637          }          }
638          *p = (char) strtol(pi.word, &end, 0);          *p = (char) strtol(pi.word, &end, 0);
639          if (end == pi.word) {          if (end == pi.word) {
640              goto error;              goto error;
641          }          }
642      }      }
643    
644      /*      /*
645       * All done.  Clean up and return.       * All done.  Clean up and return.
646       */       */
647    
648      if (pi.chan != NULL) {      if (pi.chan != NULL) {
649          Tcl_Close(NULL, pi.chan);          Tcl_Close(NULL, pi.chan);
650      }      }
651      *widthPtr = width;      *widthPtr = width;
652      *heightPtr = height;      *heightPtr = height;
653      *hotXPtr = hotX;      *hotXPtr = hotX;
654      *hotYPtr = hotY;      *hotYPtr = hotY;
655      return data;      return data;
656    
657      error:      error:
658      if (interp != NULL) {      if (interp != NULL) {
659          Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC);          Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC);
660      }      }
661            
662      errorCleanup:      errorCleanup:
663      if (data != NULL) {      if (data != NULL) {
664          ckfree(data);          ckfree(data);
665      }      }
666      if (pi.chan != NULL) {      if (pi.chan != NULL) {
667          Tcl_Close(NULL, pi.chan);          Tcl_Close(NULL, pi.chan);
668      }      }
669      return NULL;      return NULL;
670  }  }
671    
672  /*  /*
673   *----------------------------------------------------------------------   *----------------------------------------------------------------------
674   *   *
675   * NextBitmapWord --   * NextBitmapWord --
676   *   *
677   *      This procedure retrieves the next word of information (stuff   *      This procedure retrieves the next word of information (stuff
678   *      between commas or white space) from a bitmap description.   *      between commas or white space) from a bitmap description.
679   *   *
680   * Results:   * Results:
681   *      Returns TCL_OK if all went well.  In this case the next word,   *      Returns TCL_OK if all went well.  In this case the next word,
682   *      and its length, will be availble in *parseInfoPtr.  If the end   *      and its length, will be availble in *parseInfoPtr.  If the end
683   *      of the bitmap description was reached then TCL_ERROR is returned.   *      of the bitmap description was reached then TCL_ERROR is returned.
684   *   *
685   * Side effects:   * Side effects:
686   *      None.   *      None.
687   *   *
688   *----------------------------------------------------------------------   *----------------------------------------------------------------------
689   */   */
690    
691  static int  static int
692  NextBitmapWord(parseInfoPtr)  NextBitmapWord(parseInfoPtr)
693      ParseInfo *parseInfoPtr;            /* Describes what we're reading      ParseInfo *parseInfoPtr;            /* Describes what we're reading
694                                           * and where we are in it. */                                           * and where we are in it. */
695  {  {
696      char *src, *dst;      char *src, *dst;
697      int c;      int c;
698    
699      parseInfoPtr->wordLength = 0;      parseInfoPtr->wordLength = 0;
700      dst = parseInfoPtr->word;      dst = parseInfoPtr->word;
701      if (parseInfoPtr->string != NULL) {      if (parseInfoPtr->string != NULL) {
702          for (src = parseInfoPtr->string; isspace(UCHAR(*src)) || (*src == ',');          for (src = parseInfoPtr->string; isspace(UCHAR(*src)) || (*src == ',');
703                  src++) {                  src++) {
704              if (*src == 0) {              if (*src == 0) {
705                  return TCL_ERROR;                  return TCL_ERROR;
706              }              }
707          }          }
708          for ( ; !isspace(UCHAR(*src)) && (*src != ',') && (*src != 0); src++) {          for ( ; !isspace(UCHAR(*src)) && (*src != ',') && (*src != 0); src++) {
709              *dst = *src;              *dst = *src;
710              dst++;              dst++;
711              parseInfoPtr->wordLength++;              parseInfoPtr->wordLength++;
712              if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {              if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {
713                  return TCL_ERROR;                  return TCL_ERROR;
714              }              }
715          }          }
716          parseInfoPtr->string = src;          parseInfoPtr->string = src;
717      } else {      } else {
718          for (c = GetByte(parseInfoPtr->chan); isspace(UCHAR(c)) || (c == ',');          for (c = GetByte(parseInfoPtr->chan); isspace(UCHAR(c)) || (c == ',');
719                  c = GetByte(parseInfoPtr->chan)) {                  c = GetByte(parseInfoPtr->chan)) {
720              if (c == EOF) {              if (c == EOF) {
721                  return TCL_ERROR;                  return TCL_ERROR;
722              }              }
723          }          }
724          for ( ; !isspace(UCHAR(c)) && (c != ',') && (c != EOF);          for ( ; !isspace(UCHAR(c)) && (c != ',') && (c != EOF);
725                  c = GetByte(parseInfoPtr->chan)) {                  c = GetByte(parseInfoPtr->chan)) {
726              *dst = c;              *dst = c;
727              dst++;              dst++;
728              parseInfoPtr->wordLength++;              parseInfoPtr->wordLength++;
729              if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {              if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {
730                  return TCL_ERROR;                  return TCL_ERROR;
731              }              }
732          }          }
733      }      }
734      if (parseInfoPtr->wordLength == 0) {      if (parseInfoPtr->wordLength == 0) {
735          return TCL_ERROR;          return TCL_ERROR;
736      }      }
737      parseInfoPtr->word[parseInfoPtr->wordLength] = 0;      parseInfoPtr->word[parseInfoPtr->wordLength] = 0;
738      return TCL_OK;      return TCL_OK;
739  }  }
740    
741  /*  /*
742   *--------------------------------------------------------------   *--------------------------------------------------------------
743   *   *
744   * ImgBmapCmd --   * ImgBmapCmd --
745   *   *
746   *      This procedure is invoked to process the Tcl command   *      This procedure is invoked to process the Tcl command
747   *      that corresponds to an image managed by this module.   *      that corresponds to an image managed by this module.
748   *      See the user documentation for details on what it does.   *      See the user documentation for details on what it does.
749   *   *
750   * Results:   * Results:
751   *      A standard Tcl result.   *      A standard Tcl result.
752   *   *
753   * Side effects:   * Side effects:
754   *      See the user documentation.   *      See the user documentation.
755   *   *
756   *--------------------------------------------------------------   *--------------------------------------------------------------
757   */   */
758    
759  static int  static int
760  ImgBmapCmd(clientData, interp, objc, objv)  ImgBmapCmd(clientData, interp, objc, objv)
761      ClientData clientData;      /* Information about the image master. */      ClientData clientData;      /* Information about the image master. */
762      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
763      int objc;                   /* Number of arguments. */      int objc;                   /* Number of arguments. */
764      Tcl_Obj *CONST objv[];      /* Argument objects. */      Tcl_Obj *CONST objv[];      /* Argument objects. */
765  {  {
766      static char *bmapOptions[] = {"cget", "configure", (char *) NULL};      static char *bmapOptions[] = {"cget", "configure", (char *) NULL};
767      BitmapMaster *masterPtr = (BitmapMaster *) clientData;      BitmapMaster *masterPtr = (BitmapMaster *) clientData;
768      int code, index;      int code, index;
769    
770      if (objc < 2) {      if (objc < 2) {
771          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
772          return TCL_ERROR;          return TCL_ERROR;
773      }      }
774      if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0,      if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0,
775              &index) != TCL_OK) {              &index) != TCL_OK) {
776          return TCL_ERROR;          return TCL_ERROR;
777      }      }
778      switch (index) {      switch (index) {
779        case 0: {        case 0: {
780          if (objc != 3) {          if (objc != 3) {
781              Tcl_WrongNumArgs(interp, 2, objv, "option");              Tcl_WrongNumArgs(interp, 2, objv, "option");
782              return TCL_ERROR;              return TCL_ERROR;
783          }          }
784          return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,          return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
785                  (char *) masterPtr, Tcl_GetString(objv[2]), 0);                  (char *) masterPtr, Tcl_GetString(objv[2]), 0);
786        }        }
787        case 1: {        case 1: {
788          if (objc == 2) {          if (objc == 2) {
789              code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),              code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
790                      configSpecs, (char *) masterPtr, (char *) NULL, 0);                      configSpecs, (char *) masterPtr, (char *) NULL, 0);
791          } else if (objc == 3) {          } else if (objc == 3) {
792              code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),              code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
793                      configSpecs, (char *) masterPtr,                      configSpecs, (char *) masterPtr,
794                      Tcl_GetString(objv[2]), 0);                      Tcl_GetString(objv[2]), 0);
795          } else {          } else {
796              code = ImgBmapConfigureMaster(masterPtr, objc-2, objv+2,              code = ImgBmapConfigureMaster(masterPtr, objc-2, objv+2,
797                      TK_CONFIG_ARGV_ONLY);                      TK_CONFIG_ARGV_ONLY);
798          }          }
799          return code;          return code;
800        }        }
801        default: {        default: {
802          panic("bad const entries to bmapOptions in ImgBmapCmd");          panic("bad const entries to bmapOptions in ImgBmapCmd");
803        }        }
804      }      }
805      return TCL_OK;      return TCL_OK;
806  }  }
807    
808  /*  /*
809   *----------------------------------------------------------------------   *----------------------------------------------------------------------
810   *   *
811   * ImgBmapGet --   * ImgBmapGet --
812   *   *
813   *      This procedure is called for each use of a bitmap image in a   *      This procedure is called for each use of a bitmap image in a
814   *      widget.   *      widget.
815   *   *
816   * Results:   * Results:
817   *      The return value is a token for the instance, which is passed   *      The return value is a token for the instance, which is passed
818   *      back to us in calls to ImgBmapDisplay and ImgBmapFree.   *      back to us in calls to ImgBmapDisplay and ImgBmapFree.
819   *   *
820   * Side effects:   * Side effects:
821   *      A data structure is set up for the instance (or, an existing   *      A data structure is set up for the instance (or, an existing
822   *      instance is re-used for the new one).   *      instance is re-used for the new one).
823   *   *
824   *----------------------------------------------------------------------   *----------------------------------------------------------------------
825   */   */
826    
827  static ClientData  static ClientData
828  ImgBmapGet(tkwin, masterData)  ImgBmapGet(tkwin, masterData)
829      Tk_Window tkwin;            /* Window in which the instance will be      Tk_Window tkwin;            /* Window in which the instance will be
830                                   * used. */                                   * used. */
831      ClientData masterData;      /* Pointer to our master structure for the      ClientData masterData;      /* Pointer to our master structure for the
832                                   * image. */                                   * image. */
833  {  {
834      BitmapMaster *masterPtr = (BitmapMaster *) masterData;      BitmapMaster *masterPtr = (BitmapMaster *) masterData;
835      BitmapInstance *instancePtr;      BitmapInstance *instancePtr;
836    
837      /*      /*
838       * See if there is already an instance for this window.  If so       * See if there is already an instance for this window.  If so
839       * then just re-use it.       * then just re-use it.
840       */       */
841    
842      for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;      for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
843              instancePtr = instancePtr->nextPtr) {              instancePtr = instancePtr->nextPtr) {
844          if (instancePtr->tkwin == tkwin) {          if (instancePtr->tkwin == tkwin) {
845              instancePtr->refCount++;              instancePtr->refCount++;
846              return (ClientData) instancePtr;              return (ClientData) instancePtr;
847          }          }
848      }      }
849    
850      /*      /*
851       * The image isn't already in use in this window.  Make a new       * The image isn't already in use in this window.  Make a new
852       * instance of the image.       * instance of the image.
853       */       */
854    
855      instancePtr = (BitmapInstance *) ckalloc(sizeof(BitmapInstance));      instancePtr = (BitmapInstance *) ckalloc(sizeof(BitmapInstance));
856      instancePtr->refCount = 1;      instancePtr->refCount = 1;
857      instancePtr->masterPtr = masterPtr;      instancePtr->masterPtr = masterPtr;
858      instancePtr->tkwin = tkwin;      instancePtr->tkwin = tkwin;
859      instancePtr->fg = NULL;      instancePtr->fg = NULL;
860      instancePtr->bg = NULL;      instancePtr->bg = NULL;
861      instancePtr->bitmap = None;      instancePtr->bitmap = None;
862      instancePtr->mask = None;      instancePtr->mask = None;
863      instancePtr->gc = None;      instancePtr->gc = None;
864      instancePtr->nextPtr = masterPtr->instancePtr;      instancePtr->nextPtr = masterPtr->instancePtr;
865      masterPtr->instancePtr = instancePtr;      masterPtr->instancePtr = instancePtr;
866      ImgBmapConfigureInstance(instancePtr);      ImgBmapConfigureInstance(instancePtr);
867    
868      /*      /*
869       * If this is the first instance, must set the size of the image.       * If this is the first instance, must set the size of the image.
870       */       */
871    
872      if (instancePtr->nextPtr == NULL) {      if (instancePtr->nextPtr == NULL) {
873          Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,          Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
874                  masterPtr->height);                  masterPtr->height);
875      }      }
876    
877      return (ClientData) instancePtr;      return (ClientData) instancePtr;
878  }  }
879    
880  /*  /*
881   *----------------------------------------------------------------------   *----------------------------------------------------------------------
882   *   *
883   * ImgBmapDisplay --   * ImgBmapDisplay --
884   *   *
885   *      This procedure is invoked to draw a bitmap image.   *      This procedure is invoked to draw a bitmap image.
886   *   *
887   * Results:   * Results:
888   *      None.   *      None.
889   *   *
890   * Side effects:   * Side effects:
891   *      A portion of the image gets rendered in a pixmap or window.   *      A portion of the image gets rendered in a pixmap or window.
892   *   *
893   *----------------------------------------------------------------------   *----------------------------------------------------------------------
894   */   */
895    
896  static void  static void
897  ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width,  ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width,
898          height, drawableX, drawableY)          height, drawableX, drawableY)
899      ClientData clientData;      /* Pointer to BitmapInstance structure for      ClientData clientData;      /* Pointer to BitmapInstance structure for
900                                   * for instance to be displayed. */                                   * for instance to be displayed. */
901      Display *display;           /* Display on which to draw image. */      Display *display;           /* Display on which to draw image. */
902      Drawable drawable;          /* Pixmap or window in which to draw image. */      Drawable drawable;          /* Pixmap or window in which to draw image. */
903      int imageX, imageY;         /* Upper-left corner of region within image      int imageX, imageY;         /* Upper-left corner of region within image
904                                   * to draw. */                                   * to draw. */
905      int width, height;          /* Dimensions of region within image to draw. */      int width, height;          /* Dimensions of region within image to draw. */
906      int drawableX, drawableY;   /* Coordinates within drawable that      int drawableX, drawableY;   /* Coordinates within drawable that
907                                   * correspond to imageX and imageY. */                                   * correspond to imageX and imageY. */
908  {  {
909      BitmapInstance *instancePtr = (BitmapInstance *) clientData;      BitmapInstance *instancePtr = (BitmapInstance *) clientData;
910      int masking;      int masking;
911    
912      /*      /*
913       * If there's no graphics context, it means that an error occurred       * If there's no graphics context, it means that an error occurred
914       * while creating the image instance so it can't be displayed.       * while creating the image instance so it can't be displayed.
915       */       */
916    
917      if (instancePtr->gc == None) {      if (instancePtr->gc == None) {
918          return;          return;
919      }      }
920    
921      /*      /*
922       * If masking is in effect, must modify the mask origin within       * If masking is in effect, must modify the mask origin within
923       * the graphics context to line up with the image's origin.       * the graphics context to line up with the image's origin.
924       * Then draw the image and reset the clip origin, if there's       * Then draw the image and reset the clip origin, if there's
925       * a mask.       * a mask.
926       */       */
927    
928      masking = (instancePtr->mask != None) || (instancePtr->bg == NULL);      masking = (instancePtr->mask != None) || (instancePtr->bg == NULL);
929      if (masking) {      if (masking) {
930          XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,          XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
931                  drawableY - imageY);                  drawableY - imageY);
932      }      }
933      XCopyPlane(display, instancePtr->bitmap, drawable, instancePtr->gc,      XCopyPlane(display, instancePtr->bitmap, drawable, instancePtr->gc,
934              imageX, imageY, (unsigned) width, (unsigned) height,              imageX, imageY, (unsigned) width, (unsigned) height,
935              drawableX, drawableY, 1);              drawableX, drawableY, 1);
936      if (masking) {      if (masking) {
937          XSetClipOrigin(display, instancePtr->gc, 0, 0);          XSetClipOrigin(display, instancePtr->gc, 0, 0);
938      }      }
939  }  }
940    
941  /*  /*
942   *----------------------------------------------------------------------   *----------------------------------------------------------------------
943   *   *
944   * ImgBmapFree --   * ImgBmapFree --
945   *   *
946   *      This procedure is called when a widget ceases to use a   *      This procedure is called when a widget ceases to use a
947   *      particular instance of an image.   *      particular instance of an image.
948   *   *
949   * Results:   * Results:
950   *      None.   *      None.
951   *   *
952   * Side effects:   * Side effects:
953   *      Internal data structures get cleaned up.   *      Internal data structures get cleaned up.
954   *   *
955   *----------------------------------------------------------------------   *----------------------------------------------------------------------
956   */   */
957    
958  static void  static void
959  ImgBmapFree(clientData, display)  ImgBmapFree(clientData, display)
960      ClientData clientData;      /* Pointer to BitmapInstance structure for      ClientData clientData;      /* Pointer to BitmapInstance structure for
961                                   * for instance to be displayed. */                                   * for instance to be displayed. */
962      Display *display;           /* Display containing window that used image. */      Display *display;           /* Display containing window that used image. */
963  {  {
964      BitmapInstance *instancePtr = (BitmapInstance *) clientData;      BitmapInstance *instancePtr = (BitmapInstance *) clientData;
965      BitmapInstance *prevPtr;      BitmapInstance *prevPtr;
966    
967      instancePtr->refCount--;      instancePtr->refCount--;
968      if (instancePtr->refCount > 0) {      if (instancePtr->refCount > 0) {
969          return;          return;
970      }      }
971    
972      /*      /*
973       * There are no more uses of the image within this widget.  Free       * There are no more uses of the image within this widget.  Free
974       * the instance structure.       * the instance structure.
975       */       */
976    
977      if (instancePtr->fg != NULL) {      if (instancePtr->fg != NULL) {
978          Tk_FreeColor(instancePtr->fg);          Tk_FreeColor(instancePtr->fg);
979      }      }
980      if (instancePtr->bg != NULL) {      if (instancePtr->bg != NULL) {
981          Tk_FreeColor(instancePtr->bg);          Tk_FreeColor(instancePtr->bg);
982      }      }
983      if (instancePtr->bitmap != None) {      if (instancePtr->bitmap != None) {
984          Tk_FreePixmap(display, instancePtr->bitmap);          Tk_FreePixmap(display, instancePtr->bitmap);
985      }      }
986      if (instancePtr->mask != None) {      if (instancePtr->mask != None) {
987          Tk_FreePixmap(display, instancePtr->mask);          Tk_FreePixmap(display, instancePtr->mask);
988      }      }
989      if (instancePtr->gc != None) {      if (instancePtr->gc != None) {
990          Tk_FreeGC(display, instancePtr->gc);          Tk_FreeGC(display, instancePtr->gc);
991      }      }
992      if (instancePtr->masterPtr->instancePtr == instancePtr) {      if (instancePtr->masterPtr->instancePtr == instancePtr) {
993          instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;          instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
994      } else {      } else {
995          for (prevPtr = instancePtr->masterPtr->instancePtr;          for (prevPtr = instancePtr->masterPtr->instancePtr;
996                  prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {                  prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
997              /* Empty loop body */              /* Empty loop body */
998          }          }
999          prevPtr->nextPtr = instancePtr->nextPtr;          prevPtr->nextPtr = instancePtr->nextPtr;
1000      }      }
1001      ckfree((char *) instancePtr);      ckfree((char *) instancePtr);
1002  }  }
1003    
1004  /*  /*
1005   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1006   *   *
1007   * ImgBmapDelete --   * ImgBmapDelete --
1008   *   *
1009   *      This procedure is called by the image code to delete the   *      This procedure is called by the image code to delete the
1010   *      master structure for an image.   *      master structure for an image.
1011   *   *
1012   * Results:   * Results:
1013   *      None.   *      None.
1014   *   *
1015   * Side effects:   * Side effects:
1016   *      Resources associated with the image get freed.   *      Resources associated with the image get freed.
1017   *   *
1018   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1019   */   */
1020    
1021  static void  static void
1022  ImgBmapDelete(masterData)  ImgBmapDelete(masterData)
1023      ClientData masterData;      /* Pointer to BitmapMaster structure for      ClientData masterData;      /* Pointer to BitmapMaster structure for
1024                                   * image.  Must not have any more instances. */                                   * image.  Must not have any more instances. */
1025  {  {
1026      BitmapMaster *masterPtr = (BitmapMaster *) masterData;      BitmapMaster *masterPtr = (BitmapMaster *) masterData;
1027    
1028      if (masterPtr->instancePtr != NULL) {      if (masterPtr->instancePtr != NULL) {
1029          panic("tried to delete bitmap image when instances still exist");          panic("tried to delete bitmap image when instances still exist");
1030      }      }
1031      masterPtr->tkMaster = NULL;      masterPtr->tkMaster = NULL;
1032      if (masterPtr->imageCmd != NULL) {      if (masterPtr->imageCmd != NULL) {
1033          Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);          Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
1034      }      }
1035      if (masterPtr->data != NULL) {      if (masterPtr->data != NULL) {
1036          ckfree(masterPtr->data);          ckfree(masterPtr->data);
1037      }      }
1038      if (masterPtr->maskData != NULL) {      if (masterPtr->maskData != NULL) {
1039          ckfree(masterPtr->maskData);          ckfree(masterPtr->maskData);
1040      }      }
1041      Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);      Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
1042      ckfree((char *) masterPtr);      ckfree((char *) masterPtr);
1043  }  }
1044    
1045  /*  /*
1046   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1047   *   *
1048   * ImgBmapCmdDeletedProc --   * ImgBmapCmdDeletedProc --
1049   *   *
1050   *      This procedure is invoked when the image command for an image   *      This procedure is invoked when the image command for an image
1051   *      is deleted.  It deletes the image.   *      is deleted.  It deletes the image.
1052   *   *
1053   * Results:   * Results:
1054   *      None.   *      None.
1055   *   *
1056   * Side effects:   * Side effects:
1057   *      The image is deleted.   *      The image is deleted.
1058   *   *
1059   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1060   */   */
1061    
1062  static void  static void
1063  ImgBmapCmdDeletedProc(clientData)  ImgBmapCmdDeletedProc(clientData)
1064      ClientData clientData;      /* Pointer to BitmapMaster structure for      ClientData clientData;      /* Pointer to BitmapMaster structure for
1065                                   * image. */                                   * image. */
1066  {  {
1067      BitmapMaster *masterPtr = (BitmapMaster *) clientData;      BitmapMaster *masterPtr = (BitmapMaster *) clientData;
1068    
1069      masterPtr->imageCmd = NULL;      masterPtr->imageCmd = NULL;
1070      if (masterPtr->tkMaster != NULL) {      if (masterPtr->tkMaster != NULL) {
1071          Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));          Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
1072      }      }
1073  }  }
1074    
1075  /*  /*
1076   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1077   *   *
1078   * GetByte --   * GetByte --
1079   *   *
1080   *      Get the next byte from the open channel.   *      Get the next byte from the open channel.
1081   *   *
1082   * Results:   * Results:
1083   *      The next byte or EOF.   *      The next byte or EOF.
1084   *   *
1085   * Side effects:   * Side effects:
1086   *      We read from the channel.   *      We read from the channel.
1087   *   *
1088   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1089   */   */
1090    
1091  static int  static int
1092  GetByte(chan)  GetByte(chan)
1093      Tcl_Channel chan;   /* The channel we read from. */      Tcl_Channel chan;   /* The channel we read from. */
1094  {  {
1095      char buffer;      char buffer;
1096      int size;      int size;
1097    
1098      size = Tcl_Read(chan, &buffer, 1);      size = Tcl_Read(chan, &buffer, 1);
1099      if (size <= 0) {      if (size <= 0) {
1100          return EOF;          return EOF;
1101      } else {      } else {
1102          return buffer;          return buffer;
1103      }      }
1104  }  }
1105    
1106    
1107  /*  /*
1108   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1109   *   *
1110   * ImgBmapPostscript --   * ImgBmapPostscript --
1111   *   *
1112   *      This procedure is called by the image code to create   *      This procedure is called by the image code to create
1113   *      postscript output for an image.   *      postscript output for an image.
1114   *   *
1115   * Results:   * Results:
1116   *      None.   *      None.
1117   *   *
1118   * Side effects:   * Side effects:
1119   *      None.   *      None.
1120   *   *
1121   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1122   */   */
1123    
1124  static int  static int
1125  ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height,  ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height,
1126          prepass)          prepass)
1127      ClientData clientData;      ClientData clientData;
1128      Tcl_Interp *interp;      Tcl_Interp *interp;
1129      Tk_Window tkwin;      Tk_Window tkwin;
1130      Tk_PostscriptInfo psinfo;      Tk_PostscriptInfo psinfo;
1131      int x, y, width, height, prepass;      int x, y, width, height, prepass;
1132  {  {
1133      BitmapMaster *masterPtr = (BitmapMaster *) clientData;      BitmapMaster *masterPtr = (BitmapMaster *) clientData;
1134      int rowsAtOnce, rowsThisTime;      int rowsAtOnce, rowsThisTime;
1135      int curRow, yy;      int curRow, yy;
1136      char buffer[200];      char buffer[200];
1137    
1138      if (prepass) {      if (prepass) {
1139          return TCL_OK;          return TCL_OK;
1140      }      }
1141      /*      /*
1142       * Color the background, if there is one.       * Color the background, if there is one.
1143       */       */
1144    
1145      if (masterPtr->bgUid != NULL) {      if (masterPtr->bgUid != NULL) {
1146          XColor color;          XColor color;
1147          XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid,          XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid,
1148                  &color);                  &color);
1149          sprintf(buffer,          sprintf(buffer,
1150                  "%d %d moveto %d 0 rlineto 0 %d rlineto %d %s\n",                  "%d %d moveto %d 0 rlineto 0 %d rlineto %d %s\n",
1151                  x, y, width, height, -width,"0 rlineto closepath");                  x, y, width, height, -width,"0 rlineto closepath");
1152          Tcl_AppendResult(interp, buffer, (char *) NULL);          Tcl_AppendResult(interp, buffer, (char *) NULL);
1153          if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {          if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
1154              return TCL_ERROR;              return TCL_ERROR;
1155          }          }
1156          Tcl_AppendResult(interp, "fill\n", (char *) NULL);          Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1157      }      }
1158    
1159      /*      /*
1160       * Draw the bitmap, if there is a foreground color.  If the bitmap       * Draw the bitmap, if there is a foreground color.  If the bitmap
1161       * is very large, then chop it up into multiple bitmaps, each       * is very large, then chop it up into multiple bitmaps, each
1162       * consisting of one or more rows.  This is needed because Postscript       * consisting of one or more rows.  This is needed because Postscript
1163       * can't handle single strings longer than 64 KBytes long.       * can't handle single strings longer than 64 KBytes long.
1164       */       */
1165    
1166      if (masterPtr->fgUid != NULL) {      if (masterPtr->fgUid != NULL) {
1167          XColor color;          XColor color;
1168          XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid,          XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid,
1169                  &color);                  &color);
1170          if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {          if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
1171              return TCL_ERROR;              return TCL_ERROR;
1172          }          }
1173          if (width > 60000) {          if (width > 60000) {
1174              Tcl_ResetResult(interp);              Tcl_ResetResult(interp);
1175              Tcl_AppendResult(interp, "can't generate Postscript",              Tcl_AppendResult(interp, "can't generate Postscript",
1176                      " for bitmaps more than 60000 pixels wide",                      " for bitmaps more than 60000 pixels wide",
1177                      (char *) NULL);                      (char *) NULL);
1178              return TCL_ERROR;              return TCL_ERROR;
1179          }          }
1180          rowsAtOnce = 60000/width;          rowsAtOnce = 60000/width;
1181          if (rowsAtOnce < 1) {          if (rowsAtOnce < 1) {
1182              rowsAtOnce = 1;              rowsAtOnce = 1;
1183          }          }
1184          sprintf(buffer, "%d %d translate\n", x, y);          sprintf(buffer, "%d %d translate\n", x, y);
1185          Tcl_AppendResult(interp, buffer, (char *) NULL);          Tcl_AppendResult(interp, buffer, (char *) NULL);
1186          for (curRow = y+height-1; curRow >= y; curRow -= rowsAtOnce) {          for (curRow = y+height-1; curRow >= y; curRow -= rowsAtOnce) {
1187              rowsThisTime = rowsAtOnce;              rowsThisTime = rowsAtOnce;
1188              if (rowsThisTime > (curRow + 1 - y)) {              if (rowsThisTime > (curRow + 1 - y)) {
1189                  rowsThisTime = curRow + 1 - y;                  rowsThisTime = curRow + 1 - y;
1190              }              }
1191              sprintf(buffer, "%d %d", width, rowsThisTime);              sprintf(buffer, "%d %d", width, rowsThisTime);
1192              Tcl_AppendResult(interp, buffer, " true matrix {\n<",              Tcl_AppendResult(interp, buffer, " true matrix {\n<",
1193                      (char *) NULL);                      (char *) NULL);
1194              for (yy = curRow; yy >= (curRow - rowsThisTime + 1); yy--) {              for (yy = curRow; yy >= (curRow - rowsThisTime + 1); yy--) {
1195                  sprintf(buffer, "row %d\n", yy);                  sprintf(buffer, "row %d\n", yy);
1196                  Tcl_AppendResult(interp, buffer, (char *) NULL);                  Tcl_AppendResult(interp, buffer, (char *) NULL);
1197              }              }
1198              sprintf(buffer, "0 %.15g", (double) rowsThisTime);              sprintf(buffer, "0 %.15g", (double) rowsThisTime);
1199              Tcl_AppendResult(interp, ">\n} imagemask\n", buffer,              Tcl_AppendResult(interp, ">\n} imagemask\n", buffer,
1200                      " translate\n", (char *) NULL);                      " translate\n", (char *) NULL);
1201          }          }
1202      }      }
1203      return TCL_OK;      return TCL_OK;
1204  }  }
1205    
1206  /* End of tkimgbmap.c */  /* End of tkimgbmap.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25