/[dtapublic]/projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkmessage.c
ViewVC logotype

Diff of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkmessage.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   * tkMessage.c --   * tkMessage.c --
5   *   *
6   *      This module implements a message widgets for the Tk   *      This module implements a message widgets for the Tk
7   *      toolkit.  A message widget displays a multi-line string   *      toolkit.  A message widget displays a multi-line string
8   *      in a window according to a particular aspect ratio.   *      in a window according to a particular aspect ratio.
9   *   *
10   * Copyright (c) 1990-1994 The Regents of the University of California.   * Copyright (c) 1990-1994 The Regents of the University of California.
11   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
12   *   *
13   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
14   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15   *   *
16   * RCS: @(#) $Id: tkmessage.c,v 1.1.1.1 2001/06/13 05:06:15 dtashley Exp $   * RCS: @(#) $Id: tkmessage.c,v 1.1.1.1 2001/06/13 05:06:15 dtashley Exp $
17   */   */
18    
19  #include "tkPort.h"  #include "tkPort.h"
20  #include "default.h"  #include "default.h"
21  #include "tkInt.h"  #include "tkInt.h"
22    
23  /*  /*
24   * A data structure of the following type is kept for each message   * A data structure of the following type is kept for each message
25   * widget managed by this file:   * widget managed by this file:
26   */   */
27    
28  typedef struct {  typedef struct {
29      Tk_Window tkwin;            /* Window that embodies the message.  NULL      Tk_Window tkwin;            /* Window that embodies the message.  NULL
30                                   * means that the window has been destroyed                                   * means that the window has been destroyed
31                                   * but the data structures haven't yet been                                   * but the data structures haven't yet been
32                                   * cleaned up.*/                                   * cleaned up.*/
33      Display *display;           /* Display containing widget.  Used, among      Display *display;           /* Display containing widget.  Used, among
34                                   * other things, so that resources can be                                   * other things, so that resources can be
35                                   * freed even after tkwin has gone away. */                                   * freed even after tkwin has gone away. */
36      Tcl_Interp *interp;         /* Interpreter associated with message. */      Tcl_Interp *interp;         /* Interpreter associated with message. */
37      Tcl_Command widgetCmd;      /* Token for message's widget command. */      Tcl_Command widgetCmd;      /* Token for message's widget command. */
38    
39      /*      /*
40       * Information used when displaying widget:       * Information used when displaying widget:
41       */       */
42    
43      char *string;               /* String displayed in message. */      char *string;               /* String displayed in message. */
44      int numChars;               /* Number of characters in string, not      int numChars;               /* Number of characters in string, not
45                                   * including terminating NULL. */                                   * including terminating NULL. */
46      char *textVarName;          /* Name of variable (malloc'ed) or NULL.      char *textVarName;          /* Name of variable (malloc'ed) or NULL.
47                                   * If non-NULL, message displays the contents                                   * If non-NULL, message displays the contents
48                                   * of this variable. */                                   * of this variable. */
49      Tk_3DBorder border;         /* Structure used to draw 3-D border and      Tk_3DBorder border;         /* Structure used to draw 3-D border and
50                                   * background.  NULL means a border hasn't                                   * background.  NULL means a border hasn't
51                                   * been created yet. */                                   * been created yet. */
52      int borderWidth;            /* Width of border. */      int borderWidth;            /* Width of border. */
53      int relief;                 /* 3-D effect: TK_RELIEF_RAISED, etc. */      int relief;                 /* 3-D effect: TK_RELIEF_RAISED, etc. */
54      int highlightWidth;         /* Width in pixels of highlight to draw      int highlightWidth;         /* Width in pixels of highlight to draw
55                                   * around widget when it has the focus.                                   * around widget when it has the focus.
56                                   * <= 0 means don't draw a highlight. */                                   * <= 0 means don't draw a highlight. */
57      XColor *highlightBgColorPtr;      XColor *highlightBgColorPtr;
58                                  /* Color for drawing traversal highlight                                  /* Color for drawing traversal highlight
59                                   * area when highlight is off. */                                   * area when highlight is off. */
60      XColor *highlightColorPtr;  /* Color for drawing traversal highlight. */      XColor *highlightColorPtr;  /* Color for drawing traversal highlight. */
61      Tk_Font tkfont;             /* Information about text font, or NULL. */      Tk_Font tkfont;             /* Information about text font, or NULL. */
62      XColor *fgColorPtr;         /* Foreground color in normal mode. */      XColor *fgColorPtr;         /* Foreground color in normal mode. */
63      int padX, padY;             /* User-requested extra space around text. */      int padX, padY;             /* User-requested extra space around text. */
64      int width;                  /* User-requested width, in pixels.  0 means      int width;                  /* User-requested width, in pixels.  0 means
65                                   * compute width using aspect ratio below. */                                   * compute width using aspect ratio below. */
66      int aspect;                 /* Desired aspect ratio for window      int aspect;                 /* Desired aspect ratio for window
67                                   * (100*width/height). */                                   * (100*width/height). */
68      int msgWidth;               /* Width in pixels needed to display      int msgWidth;               /* Width in pixels needed to display
69                                   * message. */                                   * message. */
70      int msgHeight;              /* Height in pixels needed to display      int msgHeight;              /* Height in pixels needed to display
71                                   * message. */                                   * message. */
72      Tk_Anchor anchor;           /* Where to position text within window region      Tk_Anchor anchor;           /* Where to position text within window region
73                                   * if window is larger or smaller than                                   * if window is larger or smaller than
74                                   * needed. */                                   * needed. */
75      Tk_Justify justify;         /* Justification for text. */      Tk_Justify justify;         /* Justification for text. */
76    
77      GC textGC;                  /* GC for drawing text in normal mode. */      GC textGC;                  /* GC for drawing text in normal mode. */
78      Tk_TextLayout textLayout;   /* Saved layout information. */      Tk_TextLayout textLayout;   /* Saved layout information. */
79    
80      /*      /*
81       * Miscellaneous information:       * Miscellaneous information:
82       */       */
83    
84      Tk_Cursor cursor;           /* Current cursor for window, or None. */      Tk_Cursor cursor;           /* Current cursor for window, or None. */
85      char *takeFocus;            /* Value of -takefocus option;  not used in      char *takeFocus;            /* Value of -takefocus option;  not used in
86                                   * the C code, but used by keyboard traversal                                   * the C code, but used by keyboard traversal
87                                   * scripts.  Malloc'ed, but may be NULL. */                                   * scripts.  Malloc'ed, but may be NULL. */
88      int flags;                  /* Various flags;  see below for      int flags;                  /* Various flags;  see below for
89                                   * definitions. */                                   * definitions. */
90  } Message;  } Message;
91    
92  /*  /*
93   * Flag bits for messages:   * Flag bits for messages:
94   *   *
95   * REDRAW_PENDING:              Non-zero means a DoWhenIdle handler   * REDRAW_PENDING:              Non-zero means a DoWhenIdle handler
96   *                              has already been queued to redraw   *                              has already been queued to redraw
97   *                              this window.   *                              this window.
98   * GOT_FOCUS:                   Non-zero means this button currently   * GOT_FOCUS:                   Non-zero means this button currently
99   *                              has the input focus.   *                              has the input focus.
100   */   */
101    
102  #define REDRAW_PENDING          1  #define REDRAW_PENDING          1
103  #define GOT_FOCUS               4  #define GOT_FOCUS               4
104    
105  /*  /*
106   * Information used for argv parsing.   * Information used for argv parsing.
107   */   */
108    
109  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
110      {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor",      {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor",
111          DEF_MESSAGE_ANCHOR, Tk_Offset(Message, anchor), 0},          DEF_MESSAGE_ANCHOR, Tk_Offset(Message, anchor), 0},
112      {TK_CONFIG_INT, "-aspect", "aspect", "Aspect",      {TK_CONFIG_INT, "-aspect", "aspect", "Aspect",
113          DEF_MESSAGE_ASPECT, Tk_Offset(Message, aspect), 0},          DEF_MESSAGE_ASPECT, Tk_Offset(Message, aspect), 0},
114      {TK_CONFIG_BORDER, "-background", "background", "Background",      {TK_CONFIG_BORDER, "-background", "background", "Background",
115          DEF_MESSAGE_BG_COLOR, Tk_Offset(Message, border),          DEF_MESSAGE_BG_COLOR, Tk_Offset(Message, border),
116          TK_CONFIG_COLOR_ONLY},          TK_CONFIG_COLOR_ONLY},
117      {TK_CONFIG_BORDER, "-background", "background", "Background",      {TK_CONFIG_BORDER, "-background", "background", "Background",
118          DEF_MESSAGE_BG_MONO, Tk_Offset(Message, border),          DEF_MESSAGE_BG_MONO, Tk_Offset(Message, border),
119          TK_CONFIG_MONO_ONLY},          TK_CONFIG_MONO_ONLY},
120      {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,      {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
121          (char *) NULL, 0, 0},          (char *) NULL, 0, 0},
122      {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,      {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
123          (char *) NULL, 0, 0},          (char *) NULL, 0, 0},
124      {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",      {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
125          DEF_MESSAGE_BORDER_WIDTH, Tk_Offset(Message, borderWidth), 0},          DEF_MESSAGE_BORDER_WIDTH, Tk_Offset(Message, borderWidth), 0},
126      {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",      {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
127          DEF_MESSAGE_CURSOR, Tk_Offset(Message, cursor), TK_CONFIG_NULL_OK},          DEF_MESSAGE_CURSOR, Tk_Offset(Message, cursor), TK_CONFIG_NULL_OK},
128      {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,      {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
129          (char *) NULL, 0, 0},          (char *) NULL, 0, 0},
130      {TK_CONFIG_FONT, "-font", "font", "Font",      {TK_CONFIG_FONT, "-font", "font", "Font",
131          DEF_MESSAGE_FONT, Tk_Offset(Message, tkfont), 0},          DEF_MESSAGE_FONT, Tk_Offset(Message, tkfont), 0},
132      {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",      {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
133          DEF_MESSAGE_FG, Tk_Offset(Message, fgColorPtr), 0},          DEF_MESSAGE_FG, Tk_Offset(Message, fgColorPtr), 0},
134      {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",      {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
135          "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG,          "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG,
136          Tk_Offset(Message, highlightBgColorPtr), 0},          Tk_Offset(Message, highlightBgColorPtr), 0},
137      {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",      {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
138          DEF_MESSAGE_HIGHLIGHT, Tk_Offset(Message, highlightColorPtr), 0},          DEF_MESSAGE_HIGHLIGHT, Tk_Offset(Message, highlightColorPtr), 0},
139      {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",      {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
140          "HighlightThickness",          "HighlightThickness",
141          DEF_MESSAGE_HIGHLIGHT_WIDTH, Tk_Offset(Message, highlightWidth), 0},          DEF_MESSAGE_HIGHLIGHT_WIDTH, Tk_Offset(Message, highlightWidth), 0},
142      {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify",      {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
143          DEF_MESSAGE_JUSTIFY, Tk_Offset(Message, justify), 0},          DEF_MESSAGE_JUSTIFY, Tk_Offset(Message, justify), 0},
144      {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",      {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
145          DEF_MESSAGE_PADX, Tk_Offset(Message, padX), 0},          DEF_MESSAGE_PADX, Tk_Offset(Message, padX), 0},
146      {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",      {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
147          DEF_MESSAGE_PADY, Tk_Offset(Message, padY), 0},          DEF_MESSAGE_PADY, Tk_Offset(Message, padY), 0},
148      {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",      {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
149          DEF_MESSAGE_RELIEF, Tk_Offset(Message, relief), 0},          DEF_MESSAGE_RELIEF, Tk_Offset(Message, relief), 0},
150      {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",      {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
151          DEF_MESSAGE_TAKE_FOCUS, Tk_Offset(Message, takeFocus),          DEF_MESSAGE_TAKE_FOCUS, Tk_Offset(Message, takeFocus),
152          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
153      {TK_CONFIG_STRING, "-text", "text", "Text",      {TK_CONFIG_STRING, "-text", "text", "Text",
154          DEF_MESSAGE_TEXT, Tk_Offset(Message, string), 0},          DEF_MESSAGE_TEXT, Tk_Offset(Message, string), 0},
155      {TK_CONFIG_STRING, "-textvariable", "textVariable", "Variable",      {TK_CONFIG_STRING, "-textvariable", "textVariable", "Variable",
156          DEF_MESSAGE_TEXT_VARIABLE, Tk_Offset(Message, textVarName),          DEF_MESSAGE_TEXT_VARIABLE, Tk_Offset(Message, textVarName),
157          TK_CONFIG_NULL_OK},          TK_CONFIG_NULL_OK},
158      {TK_CONFIG_PIXELS, "-width", "width", "Width",      {TK_CONFIG_PIXELS, "-width", "width", "Width",
159          DEF_MESSAGE_WIDTH, Tk_Offset(Message, width), 0},          DEF_MESSAGE_WIDTH, Tk_Offset(Message, width), 0},
160      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
161          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
162  };  };
163    
164  /*  /*
165   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
166   */   */
167    
168  static void             MessageCmdDeletedProc _ANSI_ARGS_((  static void             MessageCmdDeletedProc _ANSI_ARGS_((
169                              ClientData clientData));                              ClientData clientData));
170  static void             MessageEventProc _ANSI_ARGS_((ClientData clientData,  static void             MessageEventProc _ANSI_ARGS_((ClientData clientData,
171                              XEvent *eventPtr));                              XEvent *eventPtr));
172  static char *           MessageTextVarProc _ANSI_ARGS_((ClientData clientData,  static char *           MessageTextVarProc _ANSI_ARGS_((ClientData clientData,
173                              Tcl_Interp *interp, char *name1, char *name2,                              Tcl_Interp *interp, char *name1, char *name2,
174                              int flags));                              int flags));
175  static int              MessageWidgetCmd _ANSI_ARGS_((ClientData clientData,  static int              MessageWidgetCmd _ANSI_ARGS_((ClientData clientData,
176                              Tcl_Interp *interp, int argc, char **argv));                              Tcl_Interp *interp, int argc, char **argv));
177  static void             MessageWorldChanged _ANSI_ARGS_((  static void             MessageWorldChanged _ANSI_ARGS_((
178                              ClientData instanceData));                              ClientData instanceData));
179  static void             ComputeMessageGeometry _ANSI_ARGS_((Message *msgPtr));  static void             ComputeMessageGeometry _ANSI_ARGS_((Message *msgPtr));
180  static int              ConfigureMessage _ANSI_ARGS_((Tcl_Interp *interp,  static int              ConfigureMessage _ANSI_ARGS_((Tcl_Interp *interp,
181                              Message *msgPtr, int argc, char **argv,                              Message *msgPtr, int argc, char **argv,
182                              int flags));                              int flags));
183  static void             DestroyMessage _ANSI_ARGS_((char *memPtr));  static void             DestroyMessage _ANSI_ARGS_((char *memPtr));
184  static void             DisplayMessage _ANSI_ARGS_((ClientData clientData));  static void             DisplayMessage _ANSI_ARGS_((ClientData clientData));
185    
186  /*  /*
187   * The structure below defines message class behavior by means of procedures   * The structure below defines message class behavior by means of procedures
188   * that can be invoked from generic window code.   * that can be invoked from generic window code.
189   */   */
190    
191  static TkClassProcs messageClass = {  static TkClassProcs messageClass = {
192      NULL,                       /* createProc. */      NULL,                       /* createProc. */
193      MessageWorldChanged,        /* geometryProc. */      MessageWorldChanged,        /* geometryProc. */
194      NULL                        /* modalProc. */      NULL                        /* modalProc. */
195  };  };
196    
197    
198  /*  /*
199   *--------------------------------------------------------------   *--------------------------------------------------------------
200   *   *
201   * Tk_MessageCmd --   * Tk_MessageCmd --
202   *   *
203   *      This procedure is invoked to process the "message" Tcl   *      This procedure is invoked to process the "message" Tcl
204   *      command.  See the user documentation for details on what   *      command.  See the user documentation for details on what
205   *      it does.   *      it does.
206   *   *
207   * Results:   * Results:
208   *      A standard Tcl result.   *      A standard Tcl result.
209   *   *
210   * Side effects:   * Side effects:
211   *      See the user documentation.   *      See the user documentation.
212   *   *
213   *--------------------------------------------------------------   *--------------------------------------------------------------
214   */   */
215    
216  int  int
217  Tk_MessageCmd(clientData, interp, argc, argv)  Tk_MessageCmd(clientData, interp, argc, argv)
218      ClientData clientData;      /* Main window associated with      ClientData clientData;      /* Main window associated with
219                                   * interpreter. */                                   * interpreter. */
220      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
221      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
222      char **argv;                /* Argument strings. */      char **argv;                /* Argument strings. */
223  {  {
224      register Message *msgPtr;      register Message *msgPtr;
225      Tk_Window new;      Tk_Window new;
226      Tk_Window tkwin = (Tk_Window) clientData;      Tk_Window tkwin = (Tk_Window) clientData;
227    
228      if (argc < 2) {      if (argc < 2) {
229          Tcl_AppendResult(interp, "wrong # args: should be \"",          Tcl_AppendResult(interp, "wrong # args: should be \"",
230                  argv[0], " pathName ?options?\"", (char *) NULL);                  argv[0], " pathName ?options?\"", (char *) NULL);
231          return TCL_ERROR;          return TCL_ERROR;
232      }      }
233    
234      new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);      new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
235      if (new == NULL) {      if (new == NULL) {
236          return TCL_ERROR;          return TCL_ERROR;
237      }      }
238    
239      msgPtr = (Message *) ckalloc(sizeof(Message));      msgPtr = (Message *) ckalloc(sizeof(Message));
240      msgPtr->tkwin = new;      msgPtr->tkwin = new;
241      msgPtr->display = Tk_Display(new);      msgPtr->display = Tk_Display(new);
242      msgPtr->interp = interp;      msgPtr->interp = interp;
243      msgPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(msgPtr->tkwin),      msgPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(msgPtr->tkwin),
244              MessageWidgetCmd, (ClientData) msgPtr, MessageCmdDeletedProc);              MessageWidgetCmd, (ClientData) msgPtr, MessageCmdDeletedProc);
245      msgPtr->textLayout = NULL;      msgPtr->textLayout = NULL;
246      msgPtr->string = NULL;      msgPtr->string = NULL;
247      msgPtr->numChars = 0;      msgPtr->numChars = 0;
248      msgPtr->textVarName = NULL;      msgPtr->textVarName = NULL;
249      msgPtr->border = NULL;      msgPtr->border = NULL;
250      msgPtr->borderWidth = 0;      msgPtr->borderWidth = 0;
251      msgPtr->relief = TK_RELIEF_FLAT;      msgPtr->relief = TK_RELIEF_FLAT;
252      msgPtr->highlightWidth = 0;      msgPtr->highlightWidth = 0;
253      msgPtr->highlightBgColorPtr = NULL;      msgPtr->highlightBgColorPtr = NULL;
254      msgPtr->highlightColorPtr = NULL;      msgPtr->highlightColorPtr = NULL;
255      msgPtr->tkfont = NULL;      msgPtr->tkfont = NULL;
256      msgPtr->fgColorPtr = NULL;      msgPtr->fgColorPtr = NULL;
257      msgPtr->textGC = None;      msgPtr->textGC = None;
258      msgPtr->padX = 0;      msgPtr->padX = 0;
259      msgPtr->padY = 0;      msgPtr->padY = 0;
260      msgPtr->anchor = TK_ANCHOR_CENTER;      msgPtr->anchor = TK_ANCHOR_CENTER;
261      msgPtr->width = 0;      msgPtr->width = 0;
262      msgPtr->aspect = 150;      msgPtr->aspect = 150;
263      msgPtr->msgWidth = 0;      msgPtr->msgWidth = 0;
264      msgPtr->msgHeight = 0;      msgPtr->msgHeight = 0;
265      msgPtr->justify = TK_JUSTIFY_LEFT;      msgPtr->justify = TK_JUSTIFY_LEFT;
266      msgPtr->cursor = None;      msgPtr->cursor = None;
267      msgPtr->takeFocus = NULL;      msgPtr->takeFocus = NULL;
268      msgPtr->flags = 0;      msgPtr->flags = 0;
269    
270      Tk_SetClass(msgPtr->tkwin, "Message");      Tk_SetClass(msgPtr->tkwin, "Message");
271      TkSetClassProcs(msgPtr->tkwin, &messageClass, (ClientData) msgPtr);      TkSetClassProcs(msgPtr->tkwin, &messageClass, (ClientData) msgPtr);
272      Tk_CreateEventHandler(msgPtr->tkwin,      Tk_CreateEventHandler(msgPtr->tkwin,
273              ExposureMask|StructureNotifyMask|FocusChangeMask,              ExposureMask|StructureNotifyMask|FocusChangeMask,
274              MessageEventProc, (ClientData) msgPtr);              MessageEventProc, (ClientData) msgPtr);
275      if (ConfigureMessage(interp, msgPtr, argc-2, argv+2, 0) != TCL_OK) {      if (ConfigureMessage(interp, msgPtr, argc-2, argv+2, 0) != TCL_OK) {
276          goto error;          goto error;
277      }      }
278    
279      Tcl_SetResult(interp, Tk_PathName(msgPtr->tkwin), TCL_STATIC);      Tcl_SetResult(interp, Tk_PathName(msgPtr->tkwin), TCL_STATIC);
280      return TCL_OK;      return TCL_OK;
281    
282      error:      error:
283      Tk_DestroyWindow(msgPtr->tkwin);      Tk_DestroyWindow(msgPtr->tkwin);
284      return TCL_ERROR;      return TCL_ERROR;
285  }  }
286    
287  /*  /*
288   *--------------------------------------------------------------   *--------------------------------------------------------------
289   *   *
290   * MessageWidgetCmd --   * MessageWidgetCmd --
291   *   *
292   *      This procedure is invoked to process the Tcl command   *      This procedure is invoked to process the Tcl command
293   *      that corresponds to a widget managed by this module.   *      that corresponds to a widget managed by this module.
294   *      See the user documentation for details on what it does.   *      See the user documentation for details on what it does.
295   *   *
296   * Results:   * Results:
297   *      A standard Tcl result.   *      A standard Tcl result.
298   *   *
299   * Side effects:   * Side effects:
300   *      See the user documentation.   *      See the user documentation.
301   *   *
302   *--------------------------------------------------------------   *--------------------------------------------------------------
303   */   */
304    
305  static int  static int
306  MessageWidgetCmd(clientData, interp, argc, argv)  MessageWidgetCmd(clientData, interp, argc, argv)
307      ClientData clientData;      /* Information about message widget. */      ClientData clientData;      /* Information about message widget. */
308      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
309      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
310      char **argv;                /* Argument strings. */      char **argv;                /* Argument strings. */
311  {  {
312      register Message *msgPtr = (Message *) clientData;      register Message *msgPtr = (Message *) clientData;
313      size_t length;      size_t length;
314      int c;      int c;
315    
316      if (argc < 2) {      if (argc < 2) {
317          Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],          Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
318                  " option ?arg arg ...?\"", (char *) NULL);                  " option ?arg arg ...?\"", (char *) NULL);
319          return TCL_ERROR;          return TCL_ERROR;
320      }      }
321      c = argv[1][0];      c = argv[1][0];
322      length = strlen(argv[1]);      length = strlen(argv[1]);
323      if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)      if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
324              && (length >= 2)) {              && (length >= 2)) {
325          if (argc != 3) {          if (argc != 3) {
326              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
327                      argv[0], " cget option\"",                      argv[0], " cget option\"",
328                      (char *) NULL);                      (char *) NULL);
329              return TCL_ERROR;              return TCL_ERROR;
330          }          }
331          return Tk_ConfigureValue(interp, msgPtr->tkwin, configSpecs,          return Tk_ConfigureValue(interp, msgPtr->tkwin, configSpecs,
332                  (char *) msgPtr, argv[2], 0);                  (char *) msgPtr, argv[2], 0);
333      } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)      } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
334              && (length  >= 2)) {              && (length  >= 2)) {
335          if (argc == 2) {          if (argc == 2) {
336              return Tk_ConfigureInfo(interp, msgPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, msgPtr->tkwin, configSpecs,
337                      (char *) msgPtr, (char *) NULL, 0);                      (char *) msgPtr, (char *) NULL, 0);
338          } else if (argc == 3) {          } else if (argc == 3) {
339              return Tk_ConfigureInfo(interp, msgPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, msgPtr->tkwin, configSpecs,
340                      (char *) msgPtr, argv[2], 0);                      (char *) msgPtr, argv[2], 0);
341          } else {          } else {
342              return ConfigureMessage(interp, msgPtr, argc-2, argv+2,              return ConfigureMessage(interp, msgPtr, argc-2, argv+2,
343                      TK_CONFIG_ARGV_ONLY);                      TK_CONFIG_ARGV_ONLY);
344          }          }
345      } else {      } else {
346          Tcl_AppendResult(interp, "bad option \"", argv[1],          Tcl_AppendResult(interp, "bad option \"", argv[1],
347                  "\": must be cget or configure", (char *) NULL);                  "\": must be cget or configure", (char *) NULL);
348          return TCL_ERROR;          return TCL_ERROR;
349      }      }
350  }  }
351    
352  /*  /*
353   *----------------------------------------------------------------------   *----------------------------------------------------------------------
354   *   *
355   * DestroyMessage --   * DestroyMessage --
356   *   *
357   *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release   *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
358   *      to clean up the internal structure of a message at a safe time   *      to clean up the internal structure of a message at a safe time
359   *      (when no-one is using it anymore).   *      (when no-one is using it anymore).
360   *   *
361   * Results:   * Results:
362   *      None.   *      None.
363   *   *
364   * Side effects:   * Side effects:
365   *      Everything associated with the message is freed up.   *      Everything associated with the message is freed up.
366   *   *
367   *----------------------------------------------------------------------   *----------------------------------------------------------------------
368   */   */
369    
370  static void  static void
371  DestroyMessage(memPtr)  DestroyMessage(memPtr)
372      char *memPtr;               /* Info about message widget. */      char *memPtr;               /* Info about message widget. */
373  {  {
374      register Message *msgPtr = (Message *) memPtr;      register Message *msgPtr = (Message *) memPtr;
375    
376      /*      /*
377       * Free up all the stuff that requires special handling, then       * Free up all the stuff that requires special handling, then
378       * let Tk_FreeOptions handle all the standard option-related       * let Tk_FreeOptions handle all the standard option-related
379       * stuff.       * stuff.
380       */       */
381    
382      Tk_FreeTextLayout(msgPtr->textLayout);      Tk_FreeTextLayout(msgPtr->textLayout);
383      if (msgPtr->textVarName != NULL) {      if (msgPtr->textVarName != NULL) {
384          Tcl_UntraceVar(msgPtr->interp, msgPtr->textVarName,          Tcl_UntraceVar(msgPtr->interp, msgPtr->textVarName,
385                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
386                  MessageTextVarProc, (ClientData) msgPtr);                  MessageTextVarProc, (ClientData) msgPtr);
387      }      }
388      if (msgPtr->textGC != None) {      if (msgPtr->textGC != None) {
389          Tk_FreeGC(msgPtr->display, msgPtr->textGC);          Tk_FreeGC(msgPtr->display, msgPtr->textGC);
390      }      }
391      Tk_FreeOptions(configSpecs, (char *) msgPtr, msgPtr->display, 0);      Tk_FreeOptions(configSpecs, (char *) msgPtr, msgPtr->display, 0);
392      ckfree((char *) msgPtr);      ckfree((char *) msgPtr);
393  }  }
394    
395  /*  /*
396   *----------------------------------------------------------------------   *----------------------------------------------------------------------
397   *   *
398   * ConfigureMessage --   * ConfigureMessage --
399   *   *
400   *      This procedure is called to process an argv/argc list, plus   *      This procedure is called to process an argv/argc list, plus
401   *      the Tk option database, in order to configure (or   *      the Tk option database, in order to configure (or
402   *      reconfigure) a message widget.   *      reconfigure) a message widget.
403   *   *
404   * Results:   * Results:
405   *      The return value is a standard Tcl result.  If TCL_ERROR is   *      The return value is a standard Tcl result.  If TCL_ERROR is
406   *      returned, then the interp's result contains an error message.   *      returned, then the interp's result contains an error message.
407   *   *
408   * Side effects:   * Side effects:
409   *      Configuration information, such as text string, colors, font,   *      Configuration information, such as text string, colors, font,
410   *      etc. get set for msgPtr;  old resources get freed, if there   *      etc. get set for msgPtr;  old resources get freed, if there
411   *      were any.   *      were any.
412   *   *
413   *----------------------------------------------------------------------   *----------------------------------------------------------------------
414   */   */
415    
416  static int  static int
417  ConfigureMessage(interp, msgPtr, argc, argv, flags)  ConfigureMessage(interp, msgPtr, argc, argv, flags)
418      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
419      register Message *msgPtr;   /* Information about widget;  may or may      register Message *msgPtr;   /* Information about widget;  may or may
420                                   * not already have values for some fields. */                                   * not already have values for some fields. */
421      int argc;                   /* Number of valid entries in argv. */      int argc;                   /* Number of valid entries in argv. */
422      char **argv;                /* Arguments. */      char **argv;                /* Arguments. */
423      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */      int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
424  {  {
425      /*      /*
426       * Eliminate any existing trace on a variable monitored by the message.       * Eliminate any existing trace on a variable monitored by the message.
427       */       */
428    
429      if (msgPtr->textVarName != NULL) {      if (msgPtr->textVarName != NULL) {
430          Tcl_UntraceVar(interp, msgPtr->textVarName,          Tcl_UntraceVar(interp, msgPtr->textVarName,
431                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
432                  MessageTextVarProc, (ClientData) msgPtr);                  MessageTextVarProc, (ClientData) msgPtr);
433      }      }
434    
435      if (Tk_ConfigureWidget(interp, msgPtr->tkwin, configSpecs,      if (Tk_ConfigureWidget(interp, msgPtr->tkwin, configSpecs,
436              argc, argv, (char *) msgPtr, flags) != TCL_OK) {              argc, argv, (char *) msgPtr, flags) != TCL_OK) {
437          return TCL_ERROR;          return TCL_ERROR;
438      }      }
439            
440      /*      /*
441       * If the message is to display the value of a variable, then set up       * If the message is to display the value of a variable, then set up
442       * a trace on the variable's value, create the variable if it doesn't       * a trace on the variable's value, create the variable if it doesn't
443       * exist, and fetch its current value.       * exist, and fetch its current value.
444       */       */
445    
446      if (msgPtr->textVarName != NULL) {      if (msgPtr->textVarName != NULL) {
447          char *value;          char *value;
448    
449          value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY);          value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY);
450          if (value == NULL) {          if (value == NULL) {
451              Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string,              Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string,
452                      TCL_GLOBAL_ONLY);                      TCL_GLOBAL_ONLY);
453          } else {          } else {
454              if (msgPtr->string != NULL) {              if (msgPtr->string != NULL) {
455                  ckfree(msgPtr->string);                  ckfree(msgPtr->string);
456              }              }
457              msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value);              msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value);
458          }          }
459          Tcl_TraceVar(interp, msgPtr->textVarName,          Tcl_TraceVar(interp, msgPtr->textVarName,
460                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
461                  MessageTextVarProc, (ClientData) msgPtr);                  MessageTextVarProc, (ClientData) msgPtr);
462      }      }
463    
464      /*      /*
465       * A few other options need special processing, such as setting       * A few other options need special processing, such as setting
466       * the background from a 3-D border or handling special defaults       * the background from a 3-D border or handling special defaults
467       * that couldn't be specified to Tk_ConfigureWidget.       * that couldn't be specified to Tk_ConfigureWidget.
468       */       */
469    
470      msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1);      msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1);
471    
472      if (msgPtr->highlightWidth < 0) {      if (msgPtr->highlightWidth < 0) {
473          msgPtr->highlightWidth = 0;          msgPtr->highlightWidth = 0;
474      }      }
475    
476      MessageWorldChanged((ClientData) msgPtr);      MessageWorldChanged((ClientData) msgPtr);
477      return TCL_OK;      return TCL_OK;
478  }  }
479    
480  /*  /*
481   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
482   *   *
483   * MessageWorldChanged --   * MessageWorldChanged --
484   *   *
485   *      This procedure is called when the world has changed in some   *      This procedure is called when the world has changed in some
486   *      way and the widget needs to recompute all its graphics contexts   *      way and the widget needs to recompute all its graphics contexts
487   *      and determine its new geometry.   *      and determine its new geometry.
488   *   *
489   * Results:   * Results:
490   *      None.   *      None.
491   *   *
492   * Side effects:   * Side effects:
493   *      Message will be relayed out and redisplayed.   *      Message will be relayed out and redisplayed.
494   *   *
495   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
496   */   */
497    
498  static void  static void
499  MessageWorldChanged(instanceData)  MessageWorldChanged(instanceData)
500      ClientData instanceData;    /* Information about widget. */      ClientData instanceData;    /* Information about widget. */
501  {  {
502      XGCValues gcValues;      XGCValues gcValues;
503      GC gc = None;      GC gc = None;
504      Tk_FontMetrics fm;      Tk_FontMetrics fm;
505      Message *msgPtr;      Message *msgPtr;
506    
507      msgPtr = (Message *) instanceData;      msgPtr = (Message *) instanceData;
508    
509      if (msgPtr->border != NULL) {      if (msgPtr->border != NULL) {
510          Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);          Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
511      }      }
512    
513      gcValues.font = Tk_FontId(msgPtr->tkfont);      gcValues.font = Tk_FontId(msgPtr->tkfont);
514      gcValues.foreground = msgPtr->fgColorPtr->pixel;      gcValues.foreground = msgPtr->fgColorPtr->pixel;
515      gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);      gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);
516      if (msgPtr->textGC != None) {      if (msgPtr->textGC != None) {
517          Tk_FreeGC(msgPtr->display, msgPtr->textGC);          Tk_FreeGC(msgPtr->display, msgPtr->textGC);
518      }      }
519      msgPtr->textGC = gc;      msgPtr->textGC = gc;
520    
521      Tk_GetFontMetrics(msgPtr->tkfont, &fm);      Tk_GetFontMetrics(msgPtr->tkfont, &fm);
522      if (msgPtr->padX < 0) {      if (msgPtr->padX < 0) {
523          msgPtr->padX = fm.ascent / 2;          msgPtr->padX = fm.ascent / 2;
524      }      }
525      if (msgPtr->padY == -1) {      if (msgPtr->padY == -1) {
526          msgPtr->padY = fm.ascent / 4;          msgPtr->padY = fm.ascent / 4;
527      }      }
528    
529      /*      /*
530       * Recompute the desired geometry for the window, and arrange for       * Recompute the desired geometry for the window, and arrange for
531       * the window to be redisplayed.       * the window to be redisplayed.
532       */       */
533    
534      ComputeMessageGeometry(msgPtr);      ComputeMessageGeometry(msgPtr);
535      if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)      if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)
536              && !(msgPtr->flags & REDRAW_PENDING)) {              && !(msgPtr->flags & REDRAW_PENDING)) {
537          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);
538          msgPtr->flags |= REDRAW_PENDING;          msgPtr->flags |= REDRAW_PENDING;
539      }      }
540  }  }
541    
542  /*  /*
543   *--------------------------------------------------------------   *--------------------------------------------------------------
544   *   *
545   * ComputeMessageGeometry --   * ComputeMessageGeometry --
546   *   *
547   *      Compute the desired geometry for a message window,   *      Compute the desired geometry for a message window,
548   *      taking into account the desired aspect ratio for the   *      taking into account the desired aspect ratio for the
549   *      window.   *      window.
550   *   *
551   * Results:   * Results:
552   *      None.   *      None.
553   *   *
554   * Side effects:   * Side effects:
555   *      Tk_GeometryRequest is called to inform the geometry   *      Tk_GeometryRequest is called to inform the geometry
556   *      manager of the desired geometry for this window.   *      manager of the desired geometry for this window.
557   *   *
558   *--------------------------------------------------------------   *--------------------------------------------------------------
559   */   */
560    
561  static void  static void
562  ComputeMessageGeometry(msgPtr)  ComputeMessageGeometry(msgPtr)
563      register Message *msgPtr;   /* Information about window. */      register Message *msgPtr;   /* Information about window. */
564  {  {
565      int width, inc, height;      int width, inc, height;
566      int thisWidth, thisHeight, maxWidth;      int thisWidth, thisHeight, maxWidth;
567      int aspect, lowerBound, upperBound, inset;      int aspect, lowerBound, upperBound, inset;
568    
569      Tk_FreeTextLayout(msgPtr->textLayout);      Tk_FreeTextLayout(msgPtr->textLayout);
570    
571      inset = msgPtr->borderWidth + msgPtr->highlightWidth;      inset = msgPtr->borderWidth + msgPtr->highlightWidth;
572    
573      /*      /*
574       * Compute acceptable bounds for the final aspect ratio.       * Compute acceptable bounds for the final aspect ratio.
575       */       */
576    
577      aspect = msgPtr->aspect/10;      aspect = msgPtr->aspect/10;
578      if (aspect < 5) {      if (aspect < 5) {
579          aspect = 5;          aspect = 5;
580      }      }
581      lowerBound = msgPtr->aspect - aspect;      lowerBound = msgPtr->aspect - aspect;
582      upperBound = msgPtr->aspect + aspect;      upperBound = msgPtr->aspect + aspect;
583    
584      /*      /*
585       * Do the computation in multiple passes:  start off with       * Do the computation in multiple passes:  start off with
586       * a very wide window, and compute its height.  Then change       * a very wide window, and compute its height.  Then change
587       * the width and try again.  Reduce the size of the change       * the width and try again.  Reduce the size of the change
588       * and iterate until dimensions are found that approximate       * and iterate until dimensions are found that approximate
589       * the desired aspect ratio.  Or, if the user gave an explicit       * the desired aspect ratio.  Or, if the user gave an explicit
590       * width then just use that.       * width then just use that.
591       */       */
592    
593      if (msgPtr->width > 0) {      if (msgPtr->width > 0) {
594          width = msgPtr->width;          width = msgPtr->width;
595          inc = 0;          inc = 0;
596      } else {      } else {
597          width = WidthOfScreen(Tk_Screen(msgPtr->tkwin))/2;          width = WidthOfScreen(Tk_Screen(msgPtr->tkwin))/2;
598          inc = width/2;          inc = width/2;
599      }      }
600    
601      for ( ; ; inc /= 2) {      for ( ; ; inc /= 2) {
602          msgPtr->textLayout = Tk_ComputeTextLayout(msgPtr->tkfont,          msgPtr->textLayout = Tk_ComputeTextLayout(msgPtr->tkfont,
603                  msgPtr->string, msgPtr->numChars, width, msgPtr->justify,                  msgPtr->string, msgPtr->numChars, width, msgPtr->justify,
604                  0, &thisWidth, &thisHeight);                  0, &thisWidth, &thisHeight);
605          maxWidth = thisWidth + 2 * (inset + msgPtr->padX);          maxWidth = thisWidth + 2 * (inset + msgPtr->padX);
606          height = thisHeight + 2 * (inset + msgPtr->padY);          height = thisHeight + 2 * (inset + msgPtr->padY);
607    
608          if (inc <= 2) {          if (inc <= 2) {
609              break;              break;
610          }          }
611          aspect = (100 * maxWidth) / height;          aspect = (100 * maxWidth) / height;
612    
613          if (aspect < lowerBound) {          if (aspect < lowerBound) {
614              width += inc;              width += inc;
615          } else if (aspect > upperBound) {          } else if (aspect > upperBound) {
616              width -= inc;              width -= inc;
617          } else {          } else {
618              break;              break;
619          }          }
620          Tk_FreeTextLayout(msgPtr->textLayout);          Tk_FreeTextLayout(msgPtr->textLayout);
621      }      }
622      msgPtr->msgWidth = thisWidth;      msgPtr->msgWidth = thisWidth;
623      msgPtr->msgHeight = thisHeight;      msgPtr->msgHeight = thisHeight;
624      Tk_GeometryRequest(msgPtr->tkwin, maxWidth, height);      Tk_GeometryRequest(msgPtr->tkwin, maxWidth, height);
625      Tk_SetInternalBorder(msgPtr->tkwin, inset);      Tk_SetInternalBorder(msgPtr->tkwin, inset);
626  }  }
627    
628  /*  /*
629   *--------------------------------------------------------------   *--------------------------------------------------------------
630   *   *
631   * DisplayMessage --   * DisplayMessage --
632   *   *
633   *      This procedure redraws the contents of a message window.   *      This procedure redraws the contents of a message window.
634   *   *
635   * Results:   * Results:
636   *      None.   *      None.
637   *   *
638   * Side effects:   * Side effects:
639   *      Information appears on the screen.   *      Information appears on the screen.
640   *   *
641   *--------------------------------------------------------------   *--------------------------------------------------------------
642   */   */
643    
644  static void  static void
645  DisplayMessage(clientData)  DisplayMessage(clientData)
646      ClientData clientData;      /* Information about window. */      ClientData clientData;      /* Information about window. */
647  {  {
648      register Message *msgPtr = (Message *) clientData;      register Message *msgPtr = (Message *) clientData;
649      register Tk_Window tkwin = msgPtr->tkwin;      register Tk_Window tkwin = msgPtr->tkwin;
650      int x, y;      int x, y;
651      int borderWidth = msgPtr->highlightWidth;      int borderWidth = msgPtr->highlightWidth;
652    
653      msgPtr->flags &= ~REDRAW_PENDING;      msgPtr->flags &= ~REDRAW_PENDING;
654      if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {      if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
655          return;          return;
656      }      }
657      if (msgPtr->border != NULL) {      if (msgPtr->border != NULL) {
658          borderWidth += msgPtr->borderWidth;          borderWidth += msgPtr->borderWidth;
659      }      }
660      if (msgPtr->relief == TK_RELIEF_FLAT) {      if (msgPtr->relief == TK_RELIEF_FLAT) {
661          borderWidth = msgPtr->highlightWidth;          borderWidth = msgPtr->highlightWidth;
662      }      }
663      Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,      Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
664              borderWidth, borderWidth,              borderWidth, borderWidth,
665              Tk_Width(tkwin) - 2 * borderWidth,              Tk_Width(tkwin) - 2 * borderWidth,
666              Tk_Height(tkwin) - 2 * borderWidth,              Tk_Height(tkwin) - 2 * borderWidth,
667              0, TK_RELIEF_FLAT);              0, TK_RELIEF_FLAT);
668    
669      /*      /*
670       * Compute starting y-location for message based on message size       * Compute starting y-location for message based on message size
671       * and anchor option.       * and anchor option.
672       */       */
673    
674      TkComputeAnchor(msgPtr->anchor, tkwin, msgPtr->padX, msgPtr->padY,      TkComputeAnchor(msgPtr->anchor, tkwin, msgPtr->padX, msgPtr->padY,
675              msgPtr->msgWidth, msgPtr->msgHeight, &x, &y);              msgPtr->msgWidth, msgPtr->msgHeight, &x, &y);
676      Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC,      Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC,
677              msgPtr->textLayout, x, y, 0, -1);              msgPtr->textLayout, x, y, 0, -1);
678    
679      if (borderWidth > msgPtr->highlightWidth) {      if (borderWidth > msgPtr->highlightWidth) {
680          Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,          Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
681                  msgPtr->highlightWidth, msgPtr->highlightWidth,                  msgPtr->highlightWidth, msgPtr->highlightWidth,
682                  Tk_Width(tkwin) - 2*msgPtr->highlightWidth,                  Tk_Width(tkwin) - 2*msgPtr->highlightWidth,
683                  Tk_Height(tkwin) - 2*msgPtr->highlightWidth,                  Tk_Height(tkwin) - 2*msgPtr->highlightWidth,
684                  msgPtr->borderWidth, msgPtr->relief);                  msgPtr->borderWidth, msgPtr->relief);
685      }      }
686      if (msgPtr->highlightWidth != 0) {      if (msgPtr->highlightWidth != 0) {
687          GC fgGC, bgGC;          GC fgGC, bgGC;
688    
689          bgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));          bgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
690          if (msgPtr->flags & GOT_FOCUS) {          if (msgPtr->flags & GOT_FOCUS) {
691              fgGC = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin));              fgGC = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin));
692              TkpDrawHighlightBorder(tkwin, fgGC, bgGC, msgPtr->highlightWidth,              TkpDrawHighlightBorder(tkwin, fgGC, bgGC, msgPtr->highlightWidth,
693                      Tk_WindowId(tkwin));                      Tk_WindowId(tkwin));
694          } else {          } else {
695              TkpDrawHighlightBorder(tkwin, bgGC, bgGC, msgPtr->highlightWidth,              TkpDrawHighlightBorder(tkwin, bgGC, bgGC, msgPtr->highlightWidth,
696                      Tk_WindowId(tkwin));                      Tk_WindowId(tkwin));
697          }          }
698      }      }
699  }  }
700    
701  /*  /*
702   *--------------------------------------------------------------   *--------------------------------------------------------------
703   *   *
704   * MessageEventProc --   * MessageEventProc --
705   *   *
706   *      This procedure is invoked by the Tk dispatcher for various   *      This procedure is invoked by the Tk dispatcher for various
707   *      events on messages.   *      events on messages.
708   *   *
709   * Results:   * Results:
710   *      None.   *      None.
711   *   *
712   * Side effects:   * Side effects:
713   *      When the window gets deleted, internal structures get   *      When the window gets deleted, internal structures get
714   *      cleaned up.  When it gets exposed, it is redisplayed.   *      cleaned up.  When it gets exposed, it is redisplayed.
715   *   *
716   *--------------------------------------------------------------   *--------------------------------------------------------------
717   */   */
718    
719  static void  static void
720  MessageEventProc(clientData, eventPtr)  MessageEventProc(clientData, eventPtr)
721      ClientData clientData;      /* Information about window. */      ClientData clientData;      /* Information about window. */
722      XEvent *eventPtr;           /* Information about event. */      XEvent *eventPtr;           /* Information about event. */
723  {  {
724      Message *msgPtr = (Message *) clientData;      Message *msgPtr = (Message *) clientData;
725    
726      if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))      if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))
727              || (eventPtr->type == ConfigureNotify)) {              || (eventPtr->type == ConfigureNotify)) {
728          goto redraw;          goto redraw;
729      } else if (eventPtr->type == DestroyNotify) {      } else if (eventPtr->type == DestroyNotify) {
730          if (msgPtr->tkwin != NULL) {          if (msgPtr->tkwin != NULL) {
731              msgPtr->tkwin = NULL;              msgPtr->tkwin = NULL;
732              Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd);              Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd);
733          }          }
734          if (msgPtr->flags & REDRAW_PENDING) {          if (msgPtr->flags & REDRAW_PENDING) {
735              Tcl_CancelIdleCall(DisplayMessage, (ClientData) msgPtr);              Tcl_CancelIdleCall(DisplayMessage, (ClientData) msgPtr);
736          }          }
737          Tcl_EventuallyFree((ClientData) msgPtr, DestroyMessage);          Tcl_EventuallyFree((ClientData) msgPtr, DestroyMessage);
738      } else if (eventPtr->type == FocusIn) {      } else if (eventPtr->type == FocusIn) {
739          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
740              msgPtr->flags |= GOT_FOCUS;              msgPtr->flags |= GOT_FOCUS;
741              if (msgPtr->highlightWidth > 0) {              if (msgPtr->highlightWidth > 0) {
742                  goto redraw;                  goto redraw;
743              }              }
744          }          }
745      } else if (eventPtr->type == FocusOut) {      } else if (eventPtr->type == FocusOut) {
746          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
747              msgPtr->flags &= ~GOT_FOCUS;              msgPtr->flags &= ~GOT_FOCUS;
748              if (msgPtr->highlightWidth > 0) {              if (msgPtr->highlightWidth > 0) {
749                  goto redraw;                  goto redraw;
750              }              }
751          }          }
752      }      }
753      return;      return;
754    
755      redraw:      redraw:
756      if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) {      if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) {
757          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);
758          msgPtr->flags |= REDRAW_PENDING;          msgPtr->flags |= REDRAW_PENDING;
759      }      }
760  }  }
761    
762  /*  /*
763   *----------------------------------------------------------------------   *----------------------------------------------------------------------
764   *   *
765   * MessageCmdDeletedProc --   * MessageCmdDeletedProc --
766   *   *
767   *      This procedure is invoked when a widget command is deleted.  If   *      This procedure is invoked when a widget command is deleted.  If
768   *      the widget isn't already in the process of being destroyed,   *      the widget isn't already in the process of being destroyed,
769   *      this command destroys it.   *      this command destroys it.
770   *   *
771   * Results:   * Results:
772   *      None.   *      None.
773   *   *
774   * Side effects:   * Side effects:
775   *      The widget is destroyed.   *      The widget is destroyed.
776   *   *
777   *----------------------------------------------------------------------   *----------------------------------------------------------------------
778   */   */
779    
780  static void  static void
781  MessageCmdDeletedProc(clientData)  MessageCmdDeletedProc(clientData)
782      ClientData clientData;      /* Pointer to widget record for widget. */      ClientData clientData;      /* Pointer to widget record for widget. */
783  {  {
784      Message *msgPtr = (Message *) clientData;      Message *msgPtr = (Message *) clientData;
785      Tk_Window tkwin = msgPtr->tkwin;      Tk_Window tkwin = msgPtr->tkwin;
786    
787      /*      /*
788       * This procedure could be invoked either because the window was       * This procedure could be invoked either because the window was
789       * destroyed and the command was then deleted (in which case tkwin       * destroyed and the command was then deleted (in which case tkwin
790       * is NULL) or because the command was deleted, and then this procedure       * is NULL) or because the command was deleted, and then this procedure
791       * destroys the widget.       * destroys the widget.
792       */       */
793    
794      if (tkwin != NULL) {      if (tkwin != NULL) {
795          msgPtr->tkwin = NULL;          msgPtr->tkwin = NULL;
796          Tk_DestroyWindow(tkwin);          Tk_DestroyWindow(tkwin);
797      }      }
798  }  }
799    
800  /*  /*
801   *--------------------------------------------------------------   *--------------------------------------------------------------
802   *   *
803   * MessageTextVarProc --   * MessageTextVarProc --
804   *   *
805   *      This procedure is invoked when someone changes the variable   *      This procedure is invoked when someone changes the variable
806   *      whose contents are to be displayed in a message.   *      whose contents are to be displayed in a message.
807   *   *
808   * Results:   * Results:
809   *      NULL is always returned.   *      NULL is always returned.
810   *   *
811   * Side effects:   * Side effects:
812   *      The text displayed in the message will change to match the   *      The text displayed in the message will change to match the
813   *      variable.   *      variable.
814   *   *
815   *--------------------------------------------------------------   *--------------------------------------------------------------
816   */   */
817    
818          /* ARGSUSED */          /* ARGSUSED */
819  static char *  static char *
820  MessageTextVarProc(clientData, interp, name1, name2, flags)  MessageTextVarProc(clientData, interp, name1, name2, flags)
821      ClientData clientData;      /* Information about message. */      ClientData clientData;      /* Information about message. */
822      Tcl_Interp *interp;         /* Interpreter containing variable. */      Tcl_Interp *interp;         /* Interpreter containing variable. */
823      char *name1;                /* Name of variable. */      char *name1;                /* Name of variable. */
824      char *name2;                /* Second part of variable name. */      char *name2;                /* Second part of variable name. */
825      int flags;                  /* Information about what happened. */      int flags;                  /* Information about what happened. */
826  {  {
827      register Message *msgPtr = (Message *) clientData;      register Message *msgPtr = (Message *) clientData;
828      char *value;      char *value;
829    
830      /*      /*
831       * If the variable is unset, then immediately recreate it unless       * If the variable is unset, then immediately recreate it unless
832       * the whole interpreter is going away.       * the whole interpreter is going away.
833       */       */
834    
835      if (flags & TCL_TRACE_UNSETS) {      if (flags & TCL_TRACE_UNSETS) {
836          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
837              Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string,              Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string,
838                      TCL_GLOBAL_ONLY);                      TCL_GLOBAL_ONLY);
839              Tcl_TraceVar(interp, msgPtr->textVarName,              Tcl_TraceVar(interp, msgPtr->textVarName,
840                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
841                      MessageTextVarProc, clientData);                      MessageTextVarProc, clientData);
842          }          }
843          return (char *) NULL;          return (char *) NULL;
844      }      }
845    
846      value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY);      value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY);
847      if (value == NULL) {      if (value == NULL) {
848          value = "";          value = "";
849      }      }
850      if (msgPtr->string != NULL) {      if (msgPtr->string != NULL) {
851          ckfree(msgPtr->string);          ckfree(msgPtr->string);
852      }      }
853      msgPtr->numChars = Tcl_NumUtfChars(value, -1);      msgPtr->numChars = Tcl_NumUtfChars(value, -1);
854      msgPtr->string = (char *) ckalloc((unsigned) (strlen(value) + 1));      msgPtr->string = (char *) ckalloc((unsigned) (strlen(value) + 1));
855      strcpy(msgPtr->string, value);      strcpy(msgPtr->string, value);
856      ComputeMessageGeometry(msgPtr);      ComputeMessageGeometry(msgPtr);
857    
858      if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)      if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)
859              && !(msgPtr->flags & REDRAW_PENDING)) {              && !(msgPtr->flags & REDRAW_PENDING)) {
860          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);          Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr);
861          msgPtr->flags |= REDRAW_PENDING;          msgPtr->flags |= REDRAW_PENDING;
862      }      }
863      return (char *) NULL;      return (char *) NULL;
864  }  }
865    
866  /* End of tkmessage.c */  /* End of tkmessage.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25