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

Diff of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tktextwind.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   * tkTextWind.c --   * tkTextWind.c --
5   *   *
6   *      This file contains code that allows arbitrary windows to be   *      This file contains code that allows arbitrary windows to be
7   *      nested inside text widgets.  It also implements the "window"   *      nested inside text widgets.  It also implements the "window"
8   *      widget command for texts.   *      widget command for texts.
9   *   *
10   * Copyright (c) 1994 The Regents of the University of California.   * Copyright (c) 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: tktextwind.c,v 1.1.1.1 2001/06/13 05:11:04 dtashley Exp $   * RCS: @(#) $Id: tktextwind.c,v 1.1.1.1 2001/06/13 05:11:04 dtashley Exp $
17   */   */
18    
19  #include "tk.h"  #include "tk.h"
20  #include "tkText.h"  #include "tkText.h"
21  #include "tkPort.h"  #include "tkPort.h"
22    
23  /*  /*
24   * The following structure is the official type record for the   * The following structure is the official type record for the
25   * embedded window geometry manager:   * embedded window geometry manager:
26   */   */
27    
28  static void             EmbWinRequestProc _ANSI_ARGS_((ClientData clientData,  static void             EmbWinRequestProc _ANSI_ARGS_((ClientData clientData,
29                              Tk_Window tkwin));                              Tk_Window tkwin));
30  static void             EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData,  static void             EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData,
31                              Tk_Window tkwin));                              Tk_Window tkwin));
32    
33  static Tk_GeomMgr textGeomType = {  static Tk_GeomMgr textGeomType = {
34      "text",                     /* name */      "text",                     /* name */
35      EmbWinRequestProc,          /* requestProc */      EmbWinRequestProc,          /* requestProc */
36      EmbWinLostSlaveProc,        /* lostSlaveProc */      EmbWinLostSlaveProc,        /* lostSlaveProc */
37  };  };
38    
39  /*  /*
40   * Definitions for alignment values:   * Definitions for alignment values:
41   */   */
42    
43  #define ALIGN_BOTTOM            0  #define ALIGN_BOTTOM            0
44  #define ALIGN_CENTER            1  #define ALIGN_CENTER            1
45  #define ALIGN_TOP               2  #define ALIGN_TOP               2
46  #define ALIGN_BASELINE          3  #define ALIGN_BASELINE          3
47    
48  /*  /*
49   * Macro that determines the size of an embedded window segment:   * Macro that determines the size of an embedded window segment:
50   */   */
51    
52  #define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \  #define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
53          + sizeof(TkTextEmbWindow)))          + sizeof(TkTextEmbWindow)))
54    
55  /*  /*
56   * Prototypes for procedures defined in this file:   * Prototypes for procedures defined in this file:
57   */   */
58    
59  static int              AlignParseProc _ANSI_ARGS_((ClientData clientData,  static int              AlignParseProc _ANSI_ARGS_((ClientData clientData,
60                              Tcl_Interp *interp, Tk_Window tkwin, char *value,                              Tcl_Interp *interp, Tk_Window tkwin, char *value,
61                              char *widgRec, int offset));                              char *widgRec, int offset));
62  static char *           AlignPrintProc _ANSI_ARGS_((ClientData clientData,  static char *           AlignPrintProc _ANSI_ARGS_((ClientData clientData,
63                              Tk_Window tkwin, char *widgRec, int offset,                              Tk_Window tkwin, char *widgRec, int offset,
64                              Tcl_FreeProc **freeProcPtr));                              Tcl_FreeProc **freeProcPtr));
65  static TkTextSegment *  EmbWinCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,  static TkTextSegment *  EmbWinCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,
66                              TkTextLine *linePtr));                              TkTextLine *linePtr));
67  static void             EmbWinCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,  static void             EmbWinCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
68                              TkTextLine *linePtr));                              TkTextLine *linePtr));
69  static void             EmbWinBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,  static void             EmbWinBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
70                              int index, int y, int lineHeight, int baseline,                              int index, int y, int lineHeight, int baseline,
71                              int *xPtr, int *yPtr, int *widthPtr,                              int *xPtr, int *yPtr, int *widthPtr,
72                              int *heightPtr));                              int *heightPtr));
73  static int              EmbWinConfigure _ANSI_ARGS_((TkText *textPtr,  static int              EmbWinConfigure _ANSI_ARGS_((TkText *textPtr,
74                              TkTextSegment *ewPtr, int argc, char **argv));                              TkTextSegment *ewPtr, int argc, char **argv));
75  static void             EmbWinDelayedUnmap _ANSI_ARGS_((  static void             EmbWinDelayedUnmap _ANSI_ARGS_((
76                              ClientData clientData));                              ClientData clientData));
77  static int              EmbWinDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,  static int              EmbWinDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,
78                              TkTextLine *linePtr, int treeGone));                              TkTextLine *linePtr, int treeGone));
79  static void             EmbWinDisplayProc _ANSI_ARGS_((  static void             EmbWinDisplayProc _ANSI_ARGS_((
80                              TkTextDispChunk *chunkPtr, int x, int y,                              TkTextDispChunk *chunkPtr, int x, int y,
81                              int lineHeight, int baseline, Display *display,                              int lineHeight, int baseline, Display *display,
82                              Drawable dst, int screenY));                              Drawable dst, int screenY));
83  static int              EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr,  static int              EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr,
84                              TkTextIndex *indexPtr, TkTextSegment *segPtr,                              TkTextIndex *indexPtr, TkTextSegment *segPtr,
85                              int offset, int maxX, int maxChars,                              int offset, int maxX, int maxChars,
86                              int noCharsYet, TkWrapMode wrapMode,                              int noCharsYet, TkWrapMode wrapMode,
87                              TkTextDispChunk *chunkPtr));                              TkTextDispChunk *chunkPtr));
88  static void             EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,  static void             EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,
89                              XEvent *eventPtr));                              XEvent *eventPtr));
90  static void             EmbWinUndisplayProc _ANSI_ARGS_((TkText *textPtr,  static void             EmbWinUndisplayProc _ANSI_ARGS_((TkText *textPtr,
91                              TkTextDispChunk *chunkPtr));                              TkTextDispChunk *chunkPtr));
92    
93  /*  /*
94   * The following structure declares the "embedded window" segment type.   * The following structure declares the "embedded window" segment type.
95   */   */
96    
97  static Tk_SegType tkTextEmbWindowType = {  static Tk_SegType tkTextEmbWindowType = {
98      "window",                                   /* name */      "window",                                   /* name */
99      0,                                          /* leftGravity */      0,                                          /* leftGravity */
100      (Tk_SegSplitProc *) NULL,                   /* splitProc */      (Tk_SegSplitProc *) NULL,                   /* splitProc */
101      EmbWinDeleteProc,                           /* deleteProc */      EmbWinDeleteProc,                           /* deleteProc */
102      EmbWinCleanupProc,                          /* cleanupProc */      EmbWinCleanupProc,                          /* cleanupProc */
103      (Tk_SegLineChangeProc *) NULL,              /* lineChangeProc */      (Tk_SegLineChangeProc *) NULL,              /* lineChangeProc */
104      EmbWinLayoutProc,                           /* layoutProc */      EmbWinLayoutProc,                           /* layoutProc */
105      EmbWinCheckProc                             /* checkProc */      EmbWinCheckProc                             /* checkProc */
106  };  };
107    
108  /*  /*
109   * Information used for parsing window configuration options:   * Information used for parsing window configuration options:
110   */   */
111    
112  static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,  static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,
113          (ClientData) NULL};          (ClientData) NULL};
114    
115  static Tk_ConfigSpec configSpecs[] = {  static Tk_ConfigSpec configSpecs[] = {
116      {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,      {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
117          "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},          "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
118      {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,      {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,
119          (char *) NULL, Tk_Offset(TkTextEmbWindow, create),          (char *) NULL, Tk_Offset(TkTextEmbWindow, create),
120          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
121      {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,      {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,
122          "0", Tk_Offset(TkTextEmbWindow, padX),          "0", Tk_Offset(TkTextEmbWindow, padX),
123          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
124      {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,      {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,
125          "0", Tk_Offset(TkTextEmbWindow, padY),          "0", Tk_Offset(TkTextEmbWindow, padY),
126          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
127      {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,      {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
128          "0", Tk_Offset(TkTextEmbWindow, stretch),          "0", Tk_Offset(TkTextEmbWindow, stretch),
129          TK_CONFIG_DONT_SET_DEFAULT},          TK_CONFIG_DONT_SET_DEFAULT},
130      {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,      {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
131          (char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin),          (char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin),
132          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},          TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
133      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
134          (char *) NULL, 0, 0}          (char *) NULL, 0, 0}
135  };  };
136    
137  /*  /*
138   *--------------------------------------------------------------   *--------------------------------------------------------------
139   *   *
140   * TkTextWindowCmd --   * TkTextWindowCmd --
141   *   *
142   *      This procedure implements the "window" widget command   *      This procedure implements the "window" widget command
143   *      for text widgets.  See the user documentation for details   *      for text widgets.  See the user documentation for details
144   *      on what it does.   *      on what it does.
145   *   *
146   * Results:   * Results:
147   *      A standard Tcl result or error.   *      A standard Tcl result or error.
148   *   *
149   * Side effects:   * Side effects:
150   *      See the user documentation.   *      See the user documentation.
151   *   *
152   *--------------------------------------------------------------   *--------------------------------------------------------------
153   */   */
154    
155  int  int
156  TkTextWindowCmd(textPtr, interp, argc, argv)  TkTextWindowCmd(textPtr, interp, argc, argv)
157      register TkText *textPtr;   /* Information about text widget. */      register TkText *textPtr;   /* Information about text widget. */
158      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
159      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
160      char **argv;                /* Argument strings.  Someone else has already      char **argv;                /* Argument strings.  Someone else has already
161                                   * parsed this command enough to know that                                   * parsed this command enough to know that
162                                   * argv[1] is "window". */                                   * argv[1] is "window". */
163  {  {
164      size_t length;      size_t length;
165      register TkTextSegment *ewPtr;      register TkTextSegment *ewPtr;
166    
167      if (argc < 3) {      if (argc < 3) {
168          Tcl_AppendResult(interp, "wrong # args: should be \"",          Tcl_AppendResult(interp, "wrong # args: should be \"",
169                  argv[0], " window option ?arg arg ...?\"", (char *) NULL);                  argv[0], " window option ?arg arg ...?\"", (char *) NULL);
170          return TCL_ERROR;          return TCL_ERROR;
171      }      }
172      length = strlen(argv[2]);      length = strlen(argv[2]);
173      if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {      if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
174          TkTextIndex index;          TkTextIndex index;
175          TkTextSegment *ewPtr;          TkTextSegment *ewPtr;
176    
177          if (argc != 5) {          if (argc != 5) {
178              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
179                      argv[0], " window cget index option\"",                      argv[0], " window cget index option\"",
180                      (char *) NULL);                      (char *) NULL);
181              return TCL_ERROR;              return TCL_ERROR;
182          }          }
183          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
184              return TCL_ERROR;              return TCL_ERROR;
185          }          }
186          ewPtr = TkTextIndexToSeg(&index, (int *) NULL);          ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
187          if (ewPtr->typePtr != &tkTextEmbWindowType) {          if (ewPtr->typePtr != &tkTextEmbWindowType) {
188              Tcl_AppendResult(interp, "no embedded window at index \"",              Tcl_AppendResult(interp, "no embedded window at index \"",
189                      argv[3], "\"", (char *) NULL);                      argv[3], "\"", (char *) NULL);
190              return TCL_ERROR;              return TCL_ERROR;
191          }          }
192          return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,          return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
193                  (char *) &ewPtr->body.ew, argv[4], 0);                  (char *) &ewPtr->body.ew, argv[4], 0);
194      } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {      } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
195          TkTextIndex index;          TkTextIndex index;
196          TkTextSegment *ewPtr;          TkTextSegment *ewPtr;
197    
198          if (argc < 4) {          if (argc < 4) {
199              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
200                      argv[0], " window configure index ?option value ...?\"",                      argv[0], " window configure index ?option value ...?\"",
201                      (char *) NULL);                      (char *) NULL);
202              return TCL_ERROR;              return TCL_ERROR;
203          }          }
204          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
205              return TCL_ERROR;              return TCL_ERROR;
206          }          }
207          ewPtr = TkTextIndexToSeg(&index, (int *) NULL);          ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
208          if (ewPtr->typePtr != &tkTextEmbWindowType) {          if (ewPtr->typePtr != &tkTextEmbWindowType) {
209              Tcl_AppendResult(interp, "no embedded window at index \"",              Tcl_AppendResult(interp, "no embedded window at index \"",
210                      argv[3], "\"", (char *) NULL);                      argv[3], "\"", (char *) NULL);
211              return TCL_ERROR;              return TCL_ERROR;
212          }          }
213          if (argc == 4) {          if (argc == 4) {
214              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
215                      (char *) &ewPtr->body.ew, (char *) NULL, 0);                      (char *) &ewPtr->body.ew, (char *) NULL, 0);
216          } else if (argc == 5) {          } else if (argc == 5) {
217              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,              return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
218                      (char *) &ewPtr->body.ew, argv[4], 0);                      (char *) &ewPtr->body.ew, argv[4], 0);
219          } else {          } else {
220              TkTextChanged(textPtr, &index, &index);              TkTextChanged(textPtr, &index, &index);
221              return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4);              return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4);
222          }          }
223      } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {      } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
224          TkTextIndex index;          TkTextIndex index;
225          int lineIndex;          int lineIndex;
226    
227          /*          /*
228           * Add a new window.  Find where to put the new window, and           * Add a new window.  Find where to put the new window, and
229           * mark that position for redisplay.           * mark that position for redisplay.
230           */           */
231    
232          if (argc < 4) {          if (argc < 4) {
233              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
234                      argv[0], " window create index ?option value ...?\"",                      argv[0], " window create index ?option value ...?\"",
235                      (char *) NULL);                      (char *) NULL);
236              return TCL_ERROR;              return TCL_ERROR;
237          }          }
238          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {          if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
239              return TCL_ERROR;              return TCL_ERROR;
240          }          }
241    
242          /*          /*
243           * Don't allow insertions on the last (dummy) line of the text.           * Don't allow insertions on the last (dummy) line of the text.
244           */           */
245            
246          lineIndex = TkBTreeLineIndex(index.linePtr);          lineIndex = TkBTreeLineIndex(index.linePtr);
247          if (lineIndex == TkBTreeNumLines(textPtr->tree)) {          if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
248              lineIndex--;              lineIndex--;
249              TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);              TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
250          }          }
251    
252          /*          /*
253           * Create the new window segment and initialize it.           * Create the new window segment and initialize it.
254           */           */
255    
256          ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);          ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);
257          ewPtr->typePtr = &tkTextEmbWindowType;          ewPtr->typePtr = &tkTextEmbWindowType;
258          ewPtr->size = 1;          ewPtr->size = 1;
259          ewPtr->body.ew.textPtr = textPtr;          ewPtr->body.ew.textPtr = textPtr;
260          ewPtr->body.ew.linePtr = NULL;          ewPtr->body.ew.linePtr = NULL;
261          ewPtr->body.ew.tkwin = NULL;          ewPtr->body.ew.tkwin = NULL;
262          ewPtr->body.ew.create = NULL;          ewPtr->body.ew.create = NULL;
263          ewPtr->body.ew.align = ALIGN_CENTER;          ewPtr->body.ew.align = ALIGN_CENTER;
264          ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;          ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
265          ewPtr->body.ew.stretch = 0;          ewPtr->body.ew.stretch = 0;
266          ewPtr->body.ew.chunkCount = 0;          ewPtr->body.ew.chunkCount = 0;
267          ewPtr->body.ew.displayed = 0;          ewPtr->body.ew.displayed = 0;
268    
269          /*          /*
270           * Link the segment into the text widget, then configure it (delete           * Link the segment into the text widget, then configure it (delete
271           * it again if the configuration fails).           * it again if the configuration fails).
272           */           */
273    
274          TkTextChanged(textPtr, &index, &index);          TkTextChanged(textPtr, &index, &index);
275          TkBTreeLinkSegment(ewPtr, &index);          TkBTreeLinkSegment(ewPtr, &index);
276          if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) {          if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) {
277              TkTextIndex index2;              TkTextIndex index2;
278    
279              TkTextIndexForwChars(&index, 1, &index2);              TkTextIndexForwChars(&index, 1, &index2);
280              TkBTreeDeleteChars(&index, &index2);              TkBTreeDeleteChars(&index, &index2);
281              return TCL_ERROR;              return TCL_ERROR;
282          }          }
283      } else if (strncmp(argv[2], "names", length) == 0) {      } else if (strncmp(argv[2], "names", length) == 0) {
284          Tcl_HashSearch search;          Tcl_HashSearch search;
285          Tcl_HashEntry *hPtr;          Tcl_HashEntry *hPtr;
286    
287          if (argc != 3) {          if (argc != 3) {
288              Tcl_AppendResult(interp, "wrong # args: should be \"",              Tcl_AppendResult(interp, "wrong # args: should be \"",
289                      argv[0], " window names\"", (char *) NULL);                      argv[0], " window names\"", (char *) NULL);
290              return TCL_ERROR;              return TCL_ERROR;
291          }          }
292          for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);          for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);
293                  hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {                  hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
294              Tcl_AppendElement(interp,              Tcl_AppendElement(interp,
295                      Tcl_GetHashKey(&textPtr->markTable, hPtr));                      Tcl_GetHashKey(&textPtr->markTable, hPtr));
296          }          }
297      } else {      } else {
298          Tcl_AppendResult(interp, "bad window option \"", argv[2],          Tcl_AppendResult(interp, "bad window option \"", argv[2],
299                  "\": must be cget, configure, create, or names",                  "\": must be cget, configure, create, or names",
300                  (char *) NULL);                  (char *) NULL);
301          return TCL_ERROR;          return TCL_ERROR;
302      }      }
303      return TCL_OK;      return TCL_OK;
304  }  }
305    
306  /*  /*
307   *--------------------------------------------------------------   *--------------------------------------------------------------
308   *   *
309   * EmbWinConfigure --   * EmbWinConfigure --
310   *   *
311   *      This procedure is called to handle configuration options   *      This procedure is called to handle configuration options
312   *      for an embedded window, using an argc/argv list.   *      for an embedded window, using an argc/argv list.
313   *   *
314   * Results:   * Results:
315   *      The return value is a standard Tcl result.  If TCL_ERROR is   *      The return value is a standard Tcl result.  If TCL_ERROR is
316   *      returned, then the interp's result contains an error message..   *      returned, then the interp's result contains an error message..
317   *   *
318   * Side effects:   * Side effects:
319   *      Configuration information for the embedded window changes,   *      Configuration information for the embedded window changes,
320   *      such as alignment, stretching, or name of the embedded   *      such as alignment, stretching, or name of the embedded
321   *      window.   *      window.
322   *   *
323   *--------------------------------------------------------------   *--------------------------------------------------------------
324   */   */
325    
326  static int  static int
327  EmbWinConfigure(textPtr, ewPtr, argc, argv)  EmbWinConfigure(textPtr, ewPtr, argc, argv)
328      TkText *textPtr;            /* Information about text widget that      TkText *textPtr;            /* Information about text widget that
329                                   * contains embedded window. */                                   * contains embedded window. */
330      TkTextSegment *ewPtr;       /* Embedded window to be configured. */      TkTextSegment *ewPtr;       /* Embedded window to be configured. */
331      int argc;                   /* Number of strings in argv. */      int argc;                   /* Number of strings in argv. */
332      char **argv;                /* Array of strings describing configuration      char **argv;                /* Array of strings describing configuration
333                                   * options. */                                   * options. */
334  {  {
335      Tk_Window oldWindow;      Tk_Window oldWindow;
336      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
337      int new;      int new;
338    
339      oldWindow = ewPtr->body.ew.tkwin;      oldWindow = ewPtr->body.ew.tkwin;
340      if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,      if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,
341              argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)              argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)
342              != TCL_OK) {              != TCL_OK) {
343          return TCL_ERROR;          return TCL_ERROR;
344      }      }
345      if (oldWindow != ewPtr->body.ew.tkwin) {      if (oldWindow != ewPtr->body.ew.tkwin) {
346          if (oldWindow != NULL) {          if (oldWindow != NULL) {
347              Tcl_DeleteHashEntry(Tcl_FindHashEntry(&textPtr->windowTable,              Tcl_DeleteHashEntry(Tcl_FindHashEntry(&textPtr->windowTable,
348                      Tk_PathName(oldWindow)));                      Tk_PathName(oldWindow)));
349              Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,              Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
350                      EmbWinStructureProc, (ClientData) ewPtr);                      EmbWinStructureProc, (ClientData) ewPtr);
351              Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,              Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
352                      (ClientData) NULL);                      (ClientData) NULL);
353              if (textPtr->tkwin != Tk_Parent(oldWindow)) {              if (textPtr->tkwin != Tk_Parent(oldWindow)) {
354                  Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);                  Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);
355              } else {              } else {
356                  Tk_UnmapWindow(oldWindow);                  Tk_UnmapWindow(oldWindow);
357              }              }
358          }          }
359          if (ewPtr->body.ew.tkwin != NULL) {          if (ewPtr->body.ew.tkwin != NULL) {
360              Tk_Window ancestor, parent;              Tk_Window ancestor, parent;
361    
362              /*              /*
363               * Make sure that the text is either the parent of the               * Make sure that the text is either the parent of the
364               * embedded window or a descendant of that parent.  Also,               * embedded window or a descendant of that parent.  Also,
365               * don't allow a top-level window to be managed inside               * don't allow a top-level window to be managed inside
366               * a text.               * a text.
367               */               */
368    
369              parent = Tk_Parent(ewPtr->body.ew.tkwin);              parent = Tk_Parent(ewPtr->body.ew.tkwin);
370              for (ancestor = textPtr->tkwin; ;              for (ancestor = textPtr->tkwin; ;
371                      ancestor = Tk_Parent(ancestor)) {                      ancestor = Tk_Parent(ancestor)) {
372                  if (ancestor == parent) {                  if (ancestor == parent) {
373                      break;                      break;
374                  }                  }
375                  if (Tk_IsTopLevel(ancestor)) {                  if (Tk_IsTopLevel(ancestor)) {
376                      badMaster:                      badMaster:
377                      Tcl_AppendResult(textPtr->interp, "can't embed ",                      Tcl_AppendResult(textPtr->interp, "can't embed ",
378                              Tk_PathName(ewPtr->body.ew.tkwin), " in ",                              Tk_PathName(ewPtr->body.ew.tkwin), " in ",
379                              Tk_PathName(textPtr->tkwin), (char *) NULL);                              Tk_PathName(textPtr->tkwin), (char *) NULL);
380                      ewPtr->body.ew.tkwin = NULL;                      ewPtr->body.ew.tkwin = NULL;
381                      return TCL_ERROR;                      return TCL_ERROR;
382                  }                  }
383              }              }
384              if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)              if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
385                      || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {                      || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {
386                  goto badMaster;                  goto badMaster;
387              }              }
388    
389              /*              /*
390               * Take over geometry management for the window, plus create               * Take over geometry management for the window, plus create
391               * an event handler to find out when it is deleted.               * an event handler to find out when it is deleted.
392               */               */
393    
394              Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,              Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
395                      (ClientData) ewPtr);                      (ClientData) ewPtr);
396              Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,              Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
397                      EmbWinStructureProc, (ClientData) ewPtr);                      EmbWinStructureProc, (ClientData) ewPtr);
398    
399              /*              /*
400               * Special trick!  Must enter into the hash table *after*               * Special trick!  Must enter into the hash table *after*
401               * calling Tk_ManageGeometry:  if the window was already managed               * calling Tk_ManageGeometry:  if the window was already managed
402               * elsewhere in this text, the Tk_ManageGeometry call will cause               * elsewhere in this text, the Tk_ManageGeometry call will cause
403               * the entry to be removed, which could potentially lose the new               * the entry to be removed, which could potentially lose the new
404               * entry.               * entry.
405               */               */
406    
407              hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,              hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
408                      Tk_PathName(ewPtr->body.ew.tkwin), &new);                      Tk_PathName(ewPtr->body.ew.tkwin), &new);
409              Tcl_SetHashValue(hPtr, ewPtr);              Tcl_SetHashValue(hPtr, ewPtr);
410    
411          }          }
412      }      }
413      return TCL_OK;      return TCL_OK;
414  }  }
415    
416  /*  /*
417   *--------------------------------------------------------------   *--------------------------------------------------------------
418   *   *
419   * AlignParseProc --   * AlignParseProc --
420   *   *
421   *      This procedure is invoked by Tk_ConfigureWidget during   *      This procedure is invoked by Tk_ConfigureWidget during
422   *      option processing to handle "-align" options for embedded   *      option processing to handle "-align" options for embedded
423   *      windows.   *      windows.
424   *   *
425   * Results:   * Results:
426   *      A standard Tcl return value.   *      A standard Tcl return value.
427   *   *
428   * Side effects:   * Side effects:
429   *      The alignment for the embedded window may change.   *      The alignment for the embedded window may change.
430   *   *
431   *--------------------------------------------------------------   *--------------------------------------------------------------
432   */   */
433    
434          /* ARGSUSED */          /* ARGSUSED */
435  static int  static int
436  AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)  AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)
437      ClientData clientData;              /* Not used.*/      ClientData clientData;              /* Not used.*/
438      Tcl_Interp *interp;                 /* Used for reporting errors. */      Tcl_Interp *interp;                 /* Used for reporting errors. */
439      Tk_Window tkwin;                    /* Window for text widget. */      Tk_Window tkwin;                    /* Window for text widget. */
440      char *value;                        /* Value of option. */      char *value;                        /* Value of option. */
441      char *widgRec;                      /* Pointer to TkTextEmbWindow      char *widgRec;                      /* Pointer to TkTextEmbWindow
442                                           * structure. */                                           * structure. */
443      int offset;                         /* Offset into item (ignored). */      int offset;                         /* Offset into item (ignored). */
444  {  {
445      register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec;      register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec;
446    
447      if (strcmp(value, "baseline") == 0) {      if (strcmp(value, "baseline") == 0) {
448          embPtr->align = ALIGN_BASELINE;          embPtr->align = ALIGN_BASELINE;
449      } else if (strcmp(value, "bottom") == 0) {      } else if (strcmp(value, "bottom") == 0) {
450          embPtr->align = ALIGN_BOTTOM;          embPtr->align = ALIGN_BOTTOM;
451      } else if (strcmp(value, "center") == 0) {      } else if (strcmp(value, "center") == 0) {
452          embPtr->align = ALIGN_CENTER;          embPtr->align = ALIGN_CENTER;
453      } else if (strcmp(value, "top") == 0) {      } else if (strcmp(value, "top") == 0) {
454          embPtr->align = ALIGN_TOP;          embPtr->align = ALIGN_TOP;
455      } else {      } else {
456          Tcl_AppendResult(interp, "bad alignment \"", value,          Tcl_AppendResult(interp, "bad alignment \"", value,
457                  "\": must be baseline, bottom, center, or top",                  "\": must be baseline, bottom, center, or top",
458                  (char *) NULL);                  (char *) NULL);
459          return TCL_ERROR;          return TCL_ERROR;
460      }      }
461      return TCL_OK;      return TCL_OK;
462  }  }
463    
464  /*  /*
465   *--------------------------------------------------------------   *--------------------------------------------------------------
466   *   *
467   * AlignPrintProc --   * AlignPrintProc --
468   *   *
469   *      This procedure is invoked by the Tk configuration code   *      This procedure is invoked by the Tk configuration code
470   *      to produce a printable string for the "-align" configuration   *      to produce a printable string for the "-align" configuration
471   *      option for embedded windows.   *      option for embedded windows.
472   *   *
473   * Results:   * Results:
474   *      The return value is a string describing the embedded   *      The return value is a string describing the embedded
475   *      window's current alignment.   *      window's current alignment.
476   *   *
477   * Side effects:   * Side effects:
478   *      None.   *      None.
479   *   *
480   *--------------------------------------------------------------   *--------------------------------------------------------------
481   */   */
482    
483          /* ARGSUSED */          /* ARGSUSED */
484  static char *  static char *
485  AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)  AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
486      ClientData clientData;              /* Ignored. */      ClientData clientData;              /* Ignored. */
487      Tk_Window tkwin;                    /* Window for text widget. */      Tk_Window tkwin;                    /* Window for text widget. */
488      char *widgRec;                      /* Pointer to TkTextEmbWindow      char *widgRec;                      /* Pointer to TkTextEmbWindow
489                                           * structure. */                                           * structure. */
490      int offset;                         /* Ignored. */      int offset;                         /* Ignored. */
491      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with      Tcl_FreeProc **freeProcPtr;         /* Pointer to variable to fill in with
492                                           * information about how to reclaim                                           * information about how to reclaim
493                                           * storage for return string. */                                           * storage for return string. */
494  {  {
495      switch (((TkTextEmbWindow *) widgRec)->align) {      switch (((TkTextEmbWindow *) widgRec)->align) {
496          case ALIGN_BASELINE:          case ALIGN_BASELINE:
497              return "baseline";              return "baseline";
498          case ALIGN_BOTTOM:          case ALIGN_BOTTOM:
499              return "bottom";              return "bottom";
500          case ALIGN_CENTER:          case ALIGN_CENTER:
501              return "center";              return "center";
502          case ALIGN_TOP:          case ALIGN_TOP:
503              return "top";              return "top";
504          default:          default:
505              return "??";              return "??";
506      }      }
507  }  }
508    
509  /*  /*
510   *--------------------------------------------------------------   *--------------------------------------------------------------
511   *   *
512   * EmbWinStructureProc --   * EmbWinStructureProc --
513   *   *
514   *      This procedure is invoked by the Tk event loop whenever   *      This procedure is invoked by the Tk event loop whenever
515   *      StructureNotify events occur for a window that's embedded   *      StructureNotify events occur for a window that's embedded
516   *      in a text widget.  This procedure's only purpose is to   *      in a text widget.  This procedure's only purpose is to
517   *      clean up when windows are deleted.   *      clean up when windows are deleted.
518   *   *
519   * Results:   * Results:
520   *      None.   *      None.
521   *   *
522   * Side effects:   * Side effects:
523   *      The window is disassociated from the window segment, and   *      The window is disassociated from the window segment, and
524   *      the portion of the text is redisplayed.   *      the portion of the text is redisplayed.
525   *   *
526   *--------------------------------------------------------------   *--------------------------------------------------------------
527   */   */
528    
529  static void  static void
530  EmbWinStructureProc(clientData, eventPtr)  EmbWinStructureProc(clientData, eventPtr)
531      ClientData clientData;      /* Pointer to record describing window item. */      ClientData clientData;      /* Pointer to record describing window item. */
532      XEvent *eventPtr;           /* Describes what just happened. */      XEvent *eventPtr;           /* Describes what just happened. */
533  {  {
534      register TkTextSegment *ewPtr = (TkTextSegment *) clientData;      register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
535      TkTextIndex index;      TkTextIndex index;
536    
537      if (eventPtr->type != DestroyNotify) {      if (eventPtr->type != DestroyNotify) {
538          return;          return;
539      }      }
540    
541      Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,      Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
542              Tk_PathName(ewPtr->body.ew.tkwin)));              Tk_PathName(ewPtr->body.ew.tkwin)));
543      ewPtr->body.ew.tkwin = NULL;      ewPtr->body.ew.tkwin = NULL;
544      index.tree = ewPtr->body.ew.textPtr->tree;      index.tree = ewPtr->body.ew.textPtr->tree;
545      index.linePtr = ewPtr->body.ew.linePtr;      index.linePtr = ewPtr->body.ew.linePtr;
546      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
547      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
548  }  }
549    
550  /*  /*
551   *--------------------------------------------------------------   *--------------------------------------------------------------
552   *   *
553   * EmbWinRequestProc --   * EmbWinRequestProc --
554   *   *
555   *      This procedure is invoked whenever a window that's associated   *      This procedure is invoked whenever a window that's associated
556   *      with a window canvas item changes its requested dimensions.   *      with a window canvas item changes its requested dimensions.
557   *   *
558   * Results:   * Results:
559   *      None.   *      None.
560   *   *
561   * Side effects:   * Side effects:
562   *      The size and location on the screen of the window may change,   *      The size and location on the screen of the window may change,
563   *      depending on the options specified for the window item.   *      depending on the options specified for the window item.
564   *   *
565   *--------------------------------------------------------------   *--------------------------------------------------------------
566   */   */
567    
568          /* ARGSUSED */          /* ARGSUSED */
569  static void  static void
570  EmbWinRequestProc(clientData, tkwin)  EmbWinRequestProc(clientData, tkwin)
571      ClientData clientData;              /* Pointer to record for window item. */      ClientData clientData;              /* Pointer to record for window item. */
572      Tk_Window tkwin;                    /* Window that changed its desired      Tk_Window tkwin;                    /* Window that changed its desired
573                                           * size. */                                           * size. */
574  {  {
575      TkTextSegment *ewPtr = (TkTextSegment *) clientData;      TkTextSegment *ewPtr = (TkTextSegment *) clientData;
576      TkTextIndex index;      TkTextIndex index;
577    
578      index.tree = ewPtr->body.ew.textPtr->tree;      index.tree = ewPtr->body.ew.textPtr->tree;
579      index.linePtr = ewPtr->body.ew.linePtr;      index.linePtr = ewPtr->body.ew.linePtr;
580      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
581      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
582  }  }
583    
584  /*  /*
585   *--------------------------------------------------------------   *--------------------------------------------------------------
586   *   *
587   * EmbWinLostSlaveProc --   * EmbWinLostSlaveProc --
588   *   *
589   *      This procedure is invoked by the Tk geometry manager when   *      This procedure is invoked by the Tk geometry manager when
590   *      a slave window managed by a text widget is claimed away   *      a slave window managed by a text widget is claimed away
591   *      by another geometry manager.   *      by another geometry manager.
592   *   *
593   * Results:   * Results:
594   *      None.   *      None.
595   *   *
596   * Side effects:   * Side effects:
597   *      The window is disassociated from the window segment, and   *      The window is disassociated from the window segment, and
598   *      the portion of the text is redisplayed.   *      the portion of the text is redisplayed.
599   *   *
600   *--------------------------------------------------------------   *--------------------------------------------------------------
601   */   */
602    
603  static void  static void
604  EmbWinLostSlaveProc(clientData, tkwin)  EmbWinLostSlaveProc(clientData, tkwin)
605      ClientData clientData;      /* Pointer to record describing window item. */      ClientData clientData;      /* Pointer to record describing window item. */
606      Tk_Window tkwin;            /* Window that was claimed away by another      Tk_Window tkwin;            /* Window that was claimed away by another
607                                   * geometry manager. */                                   * geometry manager. */
608  {  {
609      register TkTextSegment *ewPtr = (TkTextSegment *) clientData;      register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
610      TkTextIndex index;      TkTextIndex index;
611    
612      Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,      Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
613              EmbWinStructureProc, (ClientData) ewPtr);              EmbWinStructureProc, (ClientData) ewPtr);
614      Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);      Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
615      if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {      if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
616          Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);          Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
617      } else {      } else {
618          Tk_UnmapWindow(tkwin);          Tk_UnmapWindow(tkwin);
619      }      }
620      Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,      Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
621              Tk_PathName(ewPtr->body.ew.tkwin)));              Tk_PathName(ewPtr->body.ew.tkwin)));
622      ewPtr->body.ew.tkwin = NULL;      ewPtr->body.ew.tkwin = NULL;
623      index.tree = ewPtr->body.ew.textPtr->tree;      index.tree = ewPtr->body.ew.textPtr->tree;
624      index.linePtr = ewPtr->body.ew.linePtr;      index.linePtr = ewPtr->body.ew.linePtr;
625      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);      index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
626      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);      TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
627  }  }
628    
629  /*  /*
630   *--------------------------------------------------------------   *--------------------------------------------------------------
631   *   *
632   * EmbWinDeleteProc --   * EmbWinDeleteProc --
633   *   *
634   *      This procedure is invoked by the text B-tree code whenever   *      This procedure is invoked by the text B-tree code whenever
635   *      an embedded window lies in a range of characters being deleted.   *      an embedded window lies in a range of characters being deleted.
636   *   *
637   * Results:   * Results:
638   *      Returns 0 to indicate that the deletion has been accepted.   *      Returns 0 to indicate that the deletion has been accepted.
639   *   *
640   * Side effects:   * Side effects:
641   *      The embedded window is deleted, if it exists, and any resources   *      The embedded window is deleted, if it exists, and any resources
642   *      associated with it are released.   *      associated with it are released.
643   *   *
644   *--------------------------------------------------------------   *--------------------------------------------------------------
645   */   */
646    
647          /* ARGSUSED */          /* ARGSUSED */
648  static int  static int
649  EmbWinDeleteProc(ewPtr, linePtr, treeGone)  EmbWinDeleteProc(ewPtr, linePtr, treeGone)
650      TkTextSegment *ewPtr;               /* Segment being deleted. */      TkTextSegment *ewPtr;               /* Segment being deleted. */
651      TkTextLine *linePtr;                /* Line containing segment. */      TkTextLine *linePtr;                /* Line containing segment. */
652      int treeGone;                       /* Non-zero means the entire tree is      int treeGone;                       /* Non-zero means the entire tree is
653                                           * being deleted, so everything must                                           * being deleted, so everything must
654                                           * get cleaned up. */                                           * get cleaned up. */
655  {  {
656      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
657    
658      if (ewPtr->body.ew.tkwin != NULL) {      if (ewPtr->body.ew.tkwin != NULL) {
659          hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,          hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
660                  Tk_PathName(ewPtr->body.ew.tkwin));                  Tk_PathName(ewPtr->body.ew.tkwin));
661          if (hPtr != NULL) {          if (hPtr != NULL) {
662              /*              /*
663               * (It's possible for there to be no hash table entry for this               * (It's possible for there to be no hash table entry for this
664               * window, if an error occurred while creating the window segment               * window, if an error occurred while creating the window segment
665               * but before the window got added to the table)               * but before the window got added to the table)
666               */               */
667    
668              Tcl_DeleteHashEntry(hPtr);              Tcl_DeleteHashEntry(hPtr);
669          }          }
670    
671          /*          /*
672           * Delete the event handler for the window before destroying           * Delete the event handler for the window before destroying
673           * the window, so that EmbWinStructureProc doesn't get called           * the window, so that EmbWinStructureProc doesn't get called
674           * (we'll already do everything that it would have done, and           * (we'll already do everything that it would have done, and
675           * it will just get confused).           * it will just get confused).
676           */           */
677    
678          Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,          Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
679                  EmbWinStructureProc, (ClientData) ewPtr);                  EmbWinStructureProc, (ClientData) ewPtr);
680          Tk_DestroyWindow(ewPtr->body.ew.tkwin);          Tk_DestroyWindow(ewPtr->body.ew.tkwin);
681      }      }
682      Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);      Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
683      Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,      Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,
684              ewPtr->body.ew.textPtr->display, 0);              ewPtr->body.ew.textPtr->display, 0);
685      ckfree((char *) ewPtr);      ckfree((char *) ewPtr);
686      return 0;      return 0;
687  }  }
688    
689  /*  /*
690   *--------------------------------------------------------------   *--------------------------------------------------------------
691   *   *
692   * EmbWinCleanupProc --   * EmbWinCleanupProc --
693   *   *
694   *      This procedure is invoked by the B-tree code whenever a   *      This procedure is invoked by the B-tree code whenever a
695   *      segment containing an embedded window is moved from one   *      segment containing an embedded window is moved from one
696   *      line to another.   *      line to another.
697   *   *
698   * Results:   * Results:
699   *      None.   *      None.
700   *   *
701   * Side effects:   * Side effects:
702   *      The linePtr field of the segment gets updated.   *      The linePtr field of the segment gets updated.
703   *   *
704   *--------------------------------------------------------------   *--------------------------------------------------------------
705   */   */
706    
707  static TkTextSegment *  static TkTextSegment *
708  EmbWinCleanupProc(ewPtr, linePtr)  EmbWinCleanupProc(ewPtr, linePtr)
709      TkTextSegment *ewPtr;               /* Mark segment that's being moved. */      TkTextSegment *ewPtr;               /* Mark segment that's being moved. */
710      TkTextLine *linePtr;                /* Line that now contains segment. */      TkTextLine *linePtr;                /* Line that now contains segment. */
711  {  {
712      ewPtr->body.ew.linePtr = linePtr;      ewPtr->body.ew.linePtr = linePtr;
713      return ewPtr;      return ewPtr;
714  }  }
715    
716  /*  /*
717   *--------------------------------------------------------------   *--------------------------------------------------------------
718   *   *
719   * EmbWinLayoutProc --   * EmbWinLayoutProc --
720   *   *
721   *      This procedure is the "layoutProc" for embedded window   *      This procedure is the "layoutProc" for embedded window
722   *      segments.   *      segments.
723   *   *
724   * Results:   * Results:
725   *      1 is returned to indicate that the segment should be   *      1 is returned to indicate that the segment should be
726   *      displayed.  The chunkPtr structure is filled in.   *      displayed.  The chunkPtr structure is filled in.
727   *   *
728   * Side effects:   * Side effects:
729   *      None, except for filling in chunkPtr.   *      None, except for filling in chunkPtr.
730   *   *
731   *--------------------------------------------------------------   *--------------------------------------------------------------
732   */   */
733    
734          /*ARGSUSED*/          /*ARGSUSED*/
735  static int  static int
736  EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,  EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
737          noCharsYet, wrapMode, chunkPtr)          noCharsYet, wrapMode, chunkPtr)
738      TkText *textPtr;            /* Text widget being layed out. */      TkText *textPtr;            /* Text widget being layed out. */
739      TkTextIndex *indexPtr;      /* Identifies first character in chunk. */      TkTextIndex *indexPtr;      /* Identifies first character in chunk. */
740      TkTextSegment *ewPtr;       /* Segment corresponding to indexPtr. */      TkTextSegment *ewPtr;       /* Segment corresponding to indexPtr. */
741      int offset;                 /* Offset within segPtr corresponding to      int offset;                 /* Offset within segPtr corresponding to
742                                   * indexPtr (always 0). */                                   * indexPtr (always 0). */
743      int maxX;                   /* Chunk must not occupy pixels at this      int maxX;                   /* Chunk must not occupy pixels at this
744                                   * position or higher. */                                   * position or higher. */
745      int maxChars;               /* Chunk must not include more than this      int maxChars;               /* Chunk must not include more than this
746                                   * many characters. */                                   * many characters. */
747      int noCharsYet;             /* Non-zero means no characters have been      int noCharsYet;             /* Non-zero means no characters have been
748                                   * assigned to this line yet. */                                   * assigned to this line yet. */
749      TkWrapMode wrapMode;        /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,      TkWrapMode wrapMode;        /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,
750                                   * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */                                   * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
751      register TkTextDispChunk *chunkPtr;      register TkTextDispChunk *chunkPtr;
752                                  /* Structure to fill in with information                                  /* Structure to fill in with information
753                                   * about this chunk.  The x field has already                                   * about this chunk.  The x field has already
754                                   * been set by the caller. */                                   * been set by the caller. */
755  {  {
756      int width, height;      int width, height;
757    
758      if (offset != 0) {      if (offset != 0) {
759          panic("Non-zero offset in EmbWinLayoutProc");          panic("Non-zero offset in EmbWinLayoutProc");
760      }      }
761    
762      if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {      if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
763          int code, new;          int code, new;
764          Tcl_DString name;          Tcl_DString name;
765          Tk_Window ancestor;          Tk_Window ancestor;
766          Tcl_HashEntry *hPtr;          Tcl_HashEntry *hPtr;
767    
768          /*          /*
769           * The window doesn't currently exist.  Create it by evaluating           * The window doesn't currently exist.  Create it by evaluating
770           * the creation script.  The script must return the window's           * the creation script.  The script must return the window's
771           * path name:  look up that name to get back to the window           * path name:  look up that name to get back to the window
772           * token.  Then register ourselves as the geometry manager for           * token.  Then register ourselves as the geometry manager for
773           * the window.           * the window.
774           */           */
775    
776          code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);          code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);
777          if (code != TCL_OK) {          if (code != TCL_OK) {
778              createError:              createError:
779              Tcl_BackgroundError(textPtr->interp);              Tcl_BackgroundError(textPtr->interp);
780              goto gotWindow;              goto gotWindow;
781          }          }
782          Tcl_DStringInit(&name);          Tcl_DStringInit(&name);
783          Tcl_DStringAppend(&name, Tcl_GetStringResult(textPtr->interp), -1);          Tcl_DStringAppend(&name, Tcl_GetStringResult(textPtr->interp), -1);
784          Tcl_ResetResult(textPtr->interp);          Tcl_ResetResult(textPtr->interp);
785          ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,          ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
786                  Tcl_DStringValue(&name), textPtr->tkwin);                  Tcl_DStringValue(&name), textPtr->tkwin);
787          if (ewPtr->body.ew.tkwin == NULL) {          if (ewPtr->body.ew.tkwin == NULL) {
788              goto createError;              goto createError;
789          }          }
790          for (ancestor = textPtr->tkwin; ;          for (ancestor = textPtr->tkwin; ;
791                  ancestor = Tk_Parent(ancestor)) {                  ancestor = Tk_Parent(ancestor)) {
792              if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {              if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
793                  break;                  break;
794              }              }
795              if (Tk_IsTopLevel(ancestor)) {              if (Tk_IsTopLevel(ancestor)) {
796                  badMaster:                  badMaster:
797                  Tcl_AppendResult(textPtr->interp, "can't embed ",                  Tcl_AppendResult(textPtr->interp, "can't embed ",
798                          Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",                          Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",
799                          Tk_PathName(textPtr->tkwin), (char *) NULL);                          Tk_PathName(textPtr->tkwin), (char *) NULL);
800                  Tcl_BackgroundError(textPtr->interp);                  Tcl_BackgroundError(textPtr->interp);
801                  ewPtr->body.ew.tkwin = NULL;                  ewPtr->body.ew.tkwin = NULL;
802                  goto gotWindow;                  goto gotWindow;
803              }              }
804          }          }
805          if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)          if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
806                  || (textPtr->tkwin == ewPtr->body.ew.tkwin)) {                  || (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
807              goto badMaster;              goto badMaster;
808          }          }
809          Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,          Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
810                  (ClientData) ewPtr);                  (ClientData) ewPtr);
811          Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,          Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
812                  EmbWinStructureProc, (ClientData) ewPtr);                  EmbWinStructureProc, (ClientData) ewPtr);
813    
814          /*          /*
815           * Special trick!  Must enter into the hash table *after*           * Special trick!  Must enter into the hash table *after*
816           * calling Tk_ManageGeometry:  if the window was already managed           * calling Tk_ManageGeometry:  if the window was already managed
817           * elsewhere in this text, the Tk_ManageGeometry call will cause           * elsewhere in this text, the Tk_ManageGeometry call will cause
818           * the entry to be removed, which could potentially lose the new           * the entry to be removed, which could potentially lose the new
819           * entry.           * entry.
820           */           */
821    
822          hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,          hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
823                  Tk_PathName(ewPtr->body.ew.tkwin), &new);                  Tk_PathName(ewPtr->body.ew.tkwin), &new);
824          Tcl_SetHashValue(hPtr, ewPtr);          Tcl_SetHashValue(hPtr, ewPtr);
825      }      }
826    
827      /*      /*
828       * See if there's room for this window on this line.       * See if there's room for this window on this line.
829       */       */
830    
831      gotWindow:      gotWindow:
832      if (ewPtr->body.ew.tkwin == NULL) {      if (ewPtr->body.ew.tkwin == NULL) {
833          width = 0;          width = 0;
834          height = 0;          height = 0;
835      } else {      } else {
836          width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;          width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;
837          height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;          height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
838      }      }
839      if ((width > (maxX - chunkPtr->x))      if ((width > (maxX - chunkPtr->x))
840              && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {              && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
841          return 0;          return 0;
842      }      }
843    
844      /*      /*
845       * Fill in the chunk structure.       * Fill in the chunk structure.
846       */       */
847    
848      chunkPtr->displayProc = EmbWinDisplayProc;      chunkPtr->displayProc = EmbWinDisplayProc;
849      chunkPtr->undisplayProc = EmbWinUndisplayProc;      chunkPtr->undisplayProc = EmbWinUndisplayProc;
850      chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;      chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
851      chunkPtr->bboxProc = EmbWinBboxProc;      chunkPtr->bboxProc = EmbWinBboxProc;
852      chunkPtr->numBytes = 1;      chunkPtr->numBytes = 1;
853      if (ewPtr->body.ew.align == ALIGN_BASELINE) {      if (ewPtr->body.ew.align == ALIGN_BASELINE) {
854          chunkPtr->minAscent = height - ewPtr->body.ew.padY;          chunkPtr->minAscent = height - ewPtr->body.ew.padY;
855          chunkPtr->minDescent = ewPtr->body.ew.padY;          chunkPtr->minDescent = ewPtr->body.ew.padY;
856          chunkPtr->minHeight = 0;          chunkPtr->minHeight = 0;
857      } else {      } else {
858          chunkPtr->minAscent = 0;          chunkPtr->minAscent = 0;
859          chunkPtr->minDescent = 0;          chunkPtr->minDescent = 0;
860          chunkPtr->minHeight = height;          chunkPtr->minHeight = height;
861      }      }
862      chunkPtr->width = width;      chunkPtr->width = width;
863      chunkPtr->breakIndex = -1;      chunkPtr->breakIndex = -1;
864      chunkPtr->breakIndex = 1;      chunkPtr->breakIndex = 1;
865      chunkPtr->clientData = (ClientData) ewPtr;      chunkPtr->clientData = (ClientData) ewPtr;
866      ewPtr->body.ew.chunkCount += 1;      ewPtr->body.ew.chunkCount += 1;
867      return 1;      return 1;
868  }  }
869    
870  /*  /*
871   *--------------------------------------------------------------   *--------------------------------------------------------------
872   *   *
873   * EmbWinCheckProc --   * EmbWinCheckProc --
874   *   *
875   *      This procedure is invoked by the B-tree code to perform   *      This procedure is invoked by the B-tree code to perform
876   *      consistency checks on embedded windows.   *      consistency checks on embedded windows.
877   *   *
878   * Results:   * Results:
879   *      None.   *      None.
880   *   *
881   * Side effects:   * Side effects:
882   *      The procedure panics if it detects anything wrong with   *      The procedure panics if it detects anything wrong with
883   *      the embedded window.   *      the embedded window.
884   *   *
885   *--------------------------------------------------------------   *--------------------------------------------------------------
886   */   */
887    
888  static void  static void
889  EmbWinCheckProc(ewPtr, linePtr)  EmbWinCheckProc(ewPtr, linePtr)
890      TkTextSegment *ewPtr;               /* Segment to check. */      TkTextSegment *ewPtr;               /* Segment to check. */
891      TkTextLine *linePtr;                /* Line containing segment. */      TkTextLine *linePtr;                /* Line containing segment. */
892  {  {
893      if (ewPtr->nextPtr == NULL) {      if (ewPtr->nextPtr == NULL) {
894          panic("EmbWinCheckProc: embedded window is last segment in line");          panic("EmbWinCheckProc: embedded window is last segment in line");
895      }      }
896      if (ewPtr->size != 1) {      if (ewPtr->size != 1) {
897          panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);          panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
898      }      }
899  }  }
900    
901  /*  /*
902   *--------------------------------------------------------------   *--------------------------------------------------------------
903   *   *
904   * EmbWinDisplayProc --   * EmbWinDisplayProc --
905   *   *
906   *      This procedure is invoked by the text displaying code   *      This procedure is invoked by the text displaying code
907   *      when it is time to actually draw an embedded window   *      when it is time to actually draw an embedded window
908   *      chunk on the screen.   *      chunk on the screen.
909   *   *
910   * Results:   * Results:
911   *      None.   *      None.
912   *   *
913   * Side effects:   * Side effects:
914   *      The embedded window gets moved to the correct location   *      The embedded window gets moved to the correct location
915   *      and mapped onto the screen.   *      and mapped onto the screen.
916   *   *
917   *--------------------------------------------------------------   *--------------------------------------------------------------
918   */   */
919    
920  static void  static void
921  EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)  EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
922      TkTextDispChunk *chunkPtr;          /* Chunk that is to be drawn. */      TkTextDispChunk *chunkPtr;          /* Chunk that is to be drawn. */
923      int x;                              /* X-position in dst at which to      int x;                              /* X-position in dst at which to
924                                           * draw this chunk (differs from                                           * draw this chunk (differs from
925                                           * the x-position in the chunk because                                           * the x-position in the chunk because
926                                           * of scrolling). */                                           * of scrolling). */
927      int y;                              /* Top of rectangular bounding box      int y;                              /* Top of rectangular bounding box
928                                           * for line: tells where to draw this                                           * for line: tells where to draw this
929                                           * chunk in dst (x-position is in                                           * chunk in dst (x-position is in
930                                           * the chunk itself). */                                           * the chunk itself). */
931      int lineHeight;                     /* Total height of line. */      int lineHeight;                     /* Total height of line. */
932      int baseline;                       /* Offset of baseline from y. */      int baseline;                       /* Offset of baseline from y. */
933      Display *display;                   /* Display to use for drawing. */      Display *display;                   /* Display to use for drawing. */
934      Drawable dst;                       /* Pixmap or window in which to draw */      Drawable dst;                       /* Pixmap or window in which to draw */
935      int screenY;                        /* Y-coordinate in text window that      int screenY;                        /* Y-coordinate in text window that
936                                           * corresponds to y. */                                           * corresponds to y. */
937  {  {
938      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
939      int lineX, windowX, windowY, width, height;      int lineX, windowX, windowY, width, height;
940      Tk_Window tkwin;      Tk_Window tkwin;
941    
942      tkwin = ewPtr->body.ew.tkwin;      tkwin = ewPtr->body.ew.tkwin;
943      if (tkwin == NULL) {      if (tkwin == NULL) {
944          return;          return;
945      }      }
946      if ((x + chunkPtr->width) <= 0) {      if ((x + chunkPtr->width) <= 0) {
947          /*          /*
948           * The window is off-screen;  just unmap it.           * The window is off-screen;  just unmap it.
949           */           */
950    
951          if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {          if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
952              Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);              Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
953          } else {          } else {
954              Tk_UnmapWindow(tkwin);              Tk_UnmapWindow(tkwin);
955          }          }
956          return;          return;
957      }      }
958    
959      /*      /*
960       * Compute the window's location and size in the text widget, taking       * Compute the window's location and size in the text widget, taking
961       * into account the align and stretch values for the window.       * into account the align and stretch values for the window.
962       */       */
963    
964      EmbWinBboxProc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX,      EmbWinBboxProc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX,
965              &windowY, &width, &height);              &windowY, &width, &height);
966      windowX = lineX - chunkPtr->x + x;      windowX = lineX - chunkPtr->x + x;
967    
968      if (ewPtr->body.ew.textPtr->tkwin == Tk_Parent(tkwin)) {      if (ewPtr->body.ew.textPtr->tkwin == Tk_Parent(tkwin)) {
969          if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))          if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
970                  || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))                  || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
971                  || (height != Tk_Height(tkwin))) {                  || (height != Tk_Height(tkwin))) {
972              Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);              Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
973          }          }
974          Tk_MapWindow(tkwin);          Tk_MapWindow(tkwin);
975      } else {      } else {
976          Tk_MaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin,          Tk_MaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin,
977                  windowX, windowY, width, height);                  windowX, windowY, width, height);
978      }      }
979    
980      /*      /*
981       * Mark the window as displayed so that it won't get unmapped.       * Mark the window as displayed so that it won't get unmapped.
982       */       */
983    
984      ewPtr->body.ew.displayed = 1;      ewPtr->body.ew.displayed = 1;
985  }  }
986    
987  /*  /*
988   *--------------------------------------------------------------   *--------------------------------------------------------------
989   *   *
990   * EmbWinUndisplayProc --   * EmbWinUndisplayProc --
991   *   *
992   *      This procedure is called when the chunk for an embedded   *      This procedure is called when the chunk for an embedded
993   *      window is no longer going to be displayed.  It arranges   *      window is no longer going to be displayed.  It arranges
994   *      for the window associated with the chunk to be unmapped.   *      for the window associated with the chunk to be unmapped.
995   *   *
996   * Results:   * Results:
997   *      None.   *      None.
998   *   *
999   * Side effects:   * Side effects:
1000   *      The window is scheduled for unmapping.   *      The window is scheduled for unmapping.
1001   *   *
1002   *--------------------------------------------------------------   *--------------------------------------------------------------
1003   */   */
1004    
1005  static void  static void
1006  EmbWinUndisplayProc(textPtr, chunkPtr)  EmbWinUndisplayProc(textPtr, chunkPtr)
1007      TkText *textPtr;                    /* Overall information about text      TkText *textPtr;                    /* Overall information about text
1008                                           * widget. */                                           * widget. */
1009      TkTextDispChunk *chunkPtr;          /* Chunk that is about to be freed. */      TkTextDispChunk *chunkPtr;          /* Chunk that is about to be freed. */
1010  {  {
1011      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
1012    
1013      ewPtr->body.ew.chunkCount--;      ewPtr->body.ew.chunkCount--;
1014      if (ewPtr->body.ew.chunkCount == 0) {      if (ewPtr->body.ew.chunkCount == 0) {
1015          /*          /*
1016           * Don't unmap the window immediately, since there's a good chance           * Don't unmap the window immediately, since there's a good chance
1017           * that it will immediately be redisplayed, perhaps even in the           * that it will immediately be redisplayed, perhaps even in the
1018           * same place.  Instead, schedule the window to be unmapped later;           * same place.  Instead, schedule the window to be unmapped later;
1019           * the call to EmbWinDelayedUnmap will be cancelled in the likely           * the call to EmbWinDelayedUnmap will be cancelled in the likely
1020           * event that the unmap becomes unnecessary.           * event that the unmap becomes unnecessary.
1021           */           */
1022    
1023          ewPtr->body.ew.displayed = 0;          ewPtr->body.ew.displayed = 0;
1024          Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) ewPtr);          Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) ewPtr);
1025      }      }
1026  }  }
1027    
1028  /*  /*
1029   *--------------------------------------------------------------   *--------------------------------------------------------------
1030   *   *
1031   * EmbWinBboxProc --   * EmbWinBboxProc --
1032   *   *
1033   *      This procedure is called to compute the bounding box of   *      This procedure is called to compute the bounding box of
1034   *      the area occupied by an embedded window.   *      the area occupied by an embedded window.
1035   *   *
1036   * Results:   * Results:
1037   *      There is no return value.  *xPtr and *yPtr are filled in   *      There is no return value.  *xPtr and *yPtr are filled in
1038   *      with the coordinates of the upper left corner of the   *      with the coordinates of the upper left corner of the
1039   *      window, and *widthPtr and *heightPtr are filled in with   *      window, and *widthPtr and *heightPtr are filled in with
1040   *      the dimensions of the window in pixels.  Note:  not all   *      the dimensions of the window in pixels.  Note:  not all
1041   *      of the returned bbox is necessarily visible on the screen   *      of the returned bbox is necessarily visible on the screen
1042   *      (the rightmost part might be off-screen to the right,   *      (the rightmost part might be off-screen to the right,
1043   *      and the bottommost part might be off-screen to the bottom).   *      and the bottommost part might be off-screen to the bottom).
1044   *   *
1045   * Side effects:   * Side effects:
1046   *      None.   *      None.
1047   *   *
1048   *--------------------------------------------------------------   *--------------------------------------------------------------
1049   */   */
1050    
1051  static void  static void
1052  EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,  EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
1053          widthPtr, heightPtr)          widthPtr, heightPtr)
1054      TkTextDispChunk *chunkPtr;          /* Chunk containing desired char. */      TkTextDispChunk *chunkPtr;          /* Chunk containing desired char. */
1055      int index;                          /* Index of desired character within      int index;                          /* Index of desired character within
1056                                           * the chunk. */                                           * the chunk. */
1057      int y;                              /* Topmost pixel in area allocated      int y;                              /* Topmost pixel in area allocated
1058                                           * for this line. */                                           * for this line. */
1059      int lineHeight;                     /* Total height of line. */      int lineHeight;                     /* Total height of line. */
1060      int baseline;                       /* Location of line's baseline, in      int baseline;                       /* Location of line's baseline, in
1061                                           * pixels measured down from y. */                                           * pixels measured down from y. */
1062      int *xPtr, *yPtr;                   /* Gets filled in with coords of      int *xPtr, *yPtr;                   /* Gets filled in with coords of
1063                                           * character's upper-left pixel. */                                           * character's upper-left pixel. */
1064      int *widthPtr;                      /* Gets filled in with width of      int *widthPtr;                      /* Gets filled in with width of
1065                                           * character, in pixels. */                                           * character, in pixels. */
1066      int *heightPtr;                     /* Gets filled in with height of      int *heightPtr;                     /* Gets filled in with height of
1067                                           * character, in pixels. */                                           * character, in pixels. */
1068  {  {
1069      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;      TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
1070      Tk_Window tkwin;      Tk_Window tkwin;
1071    
1072      tkwin = ewPtr->body.ew.tkwin;      tkwin = ewPtr->body.ew.tkwin;
1073      if (tkwin != NULL) {      if (tkwin != NULL) {
1074          *widthPtr = Tk_ReqWidth(tkwin);          *widthPtr = Tk_ReqWidth(tkwin);
1075          *heightPtr = Tk_ReqHeight(tkwin);          *heightPtr = Tk_ReqHeight(tkwin);
1076      } else {      } else {
1077          *widthPtr = 0;          *widthPtr = 0;
1078          *heightPtr = 0;          *heightPtr = 0;
1079      }      }
1080      *xPtr = chunkPtr->x + ewPtr->body.ew.padX;      *xPtr = chunkPtr->x + ewPtr->body.ew.padX;
1081      if (ewPtr->body.ew.stretch) {      if (ewPtr->body.ew.stretch) {
1082          if (ewPtr->body.ew.align == ALIGN_BASELINE) {          if (ewPtr->body.ew.align == ALIGN_BASELINE) {
1083              *heightPtr = baseline - ewPtr->body.ew.padY;              *heightPtr = baseline - ewPtr->body.ew.padY;
1084          } else {          } else {
1085              *heightPtr = lineHeight - 2*ewPtr->body.ew.padY;              *heightPtr = lineHeight - 2*ewPtr->body.ew.padY;
1086          }          }
1087      }      }
1088      switch (ewPtr->body.ew.align) {      switch (ewPtr->body.ew.align) {
1089          case ALIGN_BOTTOM:          case ALIGN_BOTTOM:
1090              *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);              *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
1091              break;              break;
1092          case ALIGN_CENTER:          case ALIGN_CENTER:
1093              *yPtr = y + (lineHeight - *heightPtr)/2;              *yPtr = y + (lineHeight - *heightPtr)/2;
1094              break;              break;
1095          case ALIGN_TOP:          case ALIGN_TOP:
1096              *yPtr = y + ewPtr->body.ew.padY;              *yPtr = y + ewPtr->body.ew.padY;
1097              break;              break;
1098          case ALIGN_BASELINE:          case ALIGN_BASELINE:
1099              *yPtr = y + (baseline - *heightPtr);              *yPtr = y + (baseline - *heightPtr);
1100              break;              break;
1101      }      }
1102  }  }
1103    
1104  /*  /*
1105   *--------------------------------------------------------------   *--------------------------------------------------------------
1106   *   *
1107   * EmbWinDelayedUnmap --   * EmbWinDelayedUnmap --
1108   *   *
1109   *      This procedure is an idle handler that does the actual   *      This procedure is an idle handler that does the actual
1110   *      work of unmapping an embedded window.  See the comment   *      work of unmapping an embedded window.  See the comment
1111   *      in EmbWinUndisplayProc for details.   *      in EmbWinUndisplayProc for details.
1112   *   *
1113   * Results:   * Results:
1114   *      None.   *      None.
1115   *   *
1116   * Side effects:   * Side effects:
1117   *      The window gets unmapped, unless its chunk reference count   *      The window gets unmapped, unless its chunk reference count
1118   *      has become non-zero again.   *      has become non-zero again.
1119   *   *
1120   *--------------------------------------------------------------   *--------------------------------------------------------------
1121   */   */
1122    
1123  static void  static void
1124  EmbWinDelayedUnmap(clientData)  EmbWinDelayedUnmap(clientData)
1125      ClientData clientData;              /* Token for the window to      ClientData clientData;              /* Token for the window to
1126                                           * be unmapped. */                                           * be unmapped. */
1127  {  {
1128      TkTextSegment *ewPtr = (TkTextSegment *) clientData;      TkTextSegment *ewPtr = (TkTextSegment *) clientData;
1129    
1130      if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) {      if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) {
1131          if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) {          if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) {
1132              Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin,              Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin,
1133                      ewPtr->body.ew.textPtr->tkwin);                      ewPtr->body.ew.textPtr->tkwin);
1134          } else {          } else {
1135              Tk_UnmapWindow(ewPtr->body.ew.tkwin);              Tk_UnmapWindow(ewPtr->body.ew.tkwin);
1136          }          }
1137      }      }
1138  }  }
1139    
1140  /*  /*
1141   *--------------------------------------------------------------   *--------------------------------------------------------------
1142   *   *
1143   * TkTextWindowIndex --   * TkTextWindowIndex --
1144   *   *
1145   *      Given the name of an embedded window within a text widget,   *      Given the name of an embedded window within a text widget,
1146   *      returns an index corresponding to the window's position   *      returns an index corresponding to the window's position
1147   *      in the text.   *      in the text.
1148   *   *
1149   * Results:   * Results:
1150   *      The return value is 1 if there is an embedded window by   *      The return value is 1 if there is an embedded window by
1151   *      the given name in the text widget, 0 otherwise.  If the   *      the given name in the text widget, 0 otherwise.  If the
1152   *      window exists, *indexPtr is filled in with its index.   *      window exists, *indexPtr is filled in with its index.
1153   *   *
1154   * Side effects:   * Side effects:
1155   *      None.   *      None.
1156   *   *
1157   *--------------------------------------------------------------   *--------------------------------------------------------------
1158   */   */
1159    
1160  int  int
1161  TkTextWindowIndex(textPtr, name, indexPtr)  TkTextWindowIndex(textPtr, name, indexPtr)
1162      TkText *textPtr;            /* Text widget containing window. */      TkText *textPtr;            /* Text widget containing window. */
1163      char *name;                 /* Name of window. */      char *name;                 /* Name of window. */
1164      TkTextIndex *indexPtr;      /* Index information gets stored here. */      TkTextIndex *indexPtr;      /* Index information gets stored here. */
1165  {  {
1166      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
1167      TkTextSegment *ewPtr;      TkTextSegment *ewPtr;
1168    
1169      hPtr = Tcl_FindHashEntry(&textPtr->windowTable, name);      hPtr = Tcl_FindHashEntry(&textPtr->windowTable, name);
1170      if (hPtr == NULL) {      if (hPtr == NULL) {
1171          return 0;          return 0;
1172      }      }
1173      ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);      ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
1174      indexPtr->tree = textPtr->tree;      indexPtr->tree = textPtr->tree;
1175      indexPtr->linePtr = ewPtr->body.ew.linePtr;      indexPtr->linePtr = ewPtr->body.ew.linePtr;
1176      indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);      indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
1177      return 1;      return 1;
1178  }  }
1179    
1180  /* End of tktextwind.c */  /* End of tktextwind.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25