]> Pileus Git - ~andy/gtk/blob - gtk/gtktextchild.c
Remove all references to offscreen flag which was no longer used.
[~andy/gtk] / gtk / gtktextchild.c
1 /* gtktextchild.c - child pixmaps and widgets
2  * 
3  *
4  * Copyright (c) 1994 The Regents of the University of California.
5  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
6  * Copyright (c) 2000      Red Hat, Inc.
7  * Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
8  *
9  * This software is copyrighted by the Regents of the University of
10  * California, Sun Microsystems, Inc., and other parties.  The
11  * following terms apply to all files associated with the software
12  * unless explicitly disclaimed in individual files.
13  * 
14  * The authors hereby grant permission to use, copy, modify,
15  * distribute, and license this software and its documentation for any
16  * purpose, provided that existing copyright notices are retained in
17  * all copies and that this notice is included verbatim in any
18  * distributions. No written agreement, license, or royalty fee is
19  * required for any of the authorized uses.  Modifications to this
20  * software may be copyrighted by their authors and need not follow
21  * the licensing terms described here, provided that the new terms are
22  * clearly indicated on the first page of each file where they apply.
23  * 
24  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
25  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
26  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
27  * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  * 
30  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
31  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
33  * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
34  * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
35  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
36  *
37  * GOVERNMENT USE: If you are acquiring this software on behalf of the
38  * U.S. government, the Government shall have only "Restricted Rights"
39  * in the software and related documentation as defined in the Federal
40  * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
41  * are acquiring the software on behalf of the Department of Defense,
42  * the software shall be classified as "Commercial Computer Software"
43  * and the Government shall have only "Restricted Rights" as defined
44  * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
45  * foregoing, the authors grant the U.S. Government and others acting
46  * in its behalf permission to use and distribute the software in
47  * accordance with the terms specified in this license.
48  * 
49  */
50
51 #include "gtktextchild.h"
52 #include "gtktextbtree.h"
53
54 static GtkTextLineSegment *
55 pixmap_segment_cleanup_func(GtkTextLineSegment *seg,
56                             GtkTextLine *line)
57 {
58   /* nothing */
59   return seg;
60 }
61
62 static int
63 pixmap_segment_delete_func(GtkTextLineSegment *seg,
64                            GtkTextLine *line,
65                            gboolean tree_gone)
66 {
67   if (seg->body.pixmap.pixmap)
68     gdk_pixmap_unref(seg->body.pixmap.pixmap);
69
70   if (seg->body.pixmap.mask)
71     gdk_bitmap_unref(seg->body.pixmap.mask);
72
73   g_free(seg);
74
75   return 0;
76 }
77
78 static void
79 pixmap_segment_check_func(GtkTextLineSegment *seg,
80                           GtkTextLine *line)
81 {
82   if (seg->next == NULL)
83     g_error("pixmap segment is the last segment in a line");
84
85   if (seg->byte_count != 3)
86     g_error("pixmap segment has byte count of %d", seg->byte_count);
87
88   if (seg->char_count != 1)
89     g_error("pixmap segment has char count of %d", seg->char_count);  
90 }
91
92
93 GtkTextLineSegmentClass gtk_text_pixmap_type = {
94   "pixmap",                          /* name */
95   0,                                            /* leftGravity */
96   NULL,                                          /* splitFunc */
97   pixmap_segment_delete_func,                             /* deleteFunc */
98   pixmap_segment_cleanup_func,                            /* cleanupFunc */
99   NULL,                                                    /* lineChangeFunc */
100   pixmap_segment_check_func                               /* checkFunc */
101
102 };
103
104 #if 0
105 GtkTextLineSegmentClass gtk_text_view_child_type = {
106   "child-widget",                                       /* name */
107   0,                                            /* leftGravity */
108   child_segment_split_func,                              /* splitFunc */
109   child_segment_delete_func,                             /* deleteFunc */
110   child_segment_cleanup_func,                            /* cleanupFunc */
111   NULL,                                                    /* lineChangeFunc */
112   child_segment_check_func                               /* checkFunc */
113 };
114 #endif
115
116 #define PIXMAP_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET(GtkTextLineSegment, body) \
117         + sizeof(GtkTextPixmap)))
118
119 GtkTextLineSegment *
120 gtk_text_pixmap_segment_new(GdkPixmap *pixmap, GdkBitmap *mask)
121 {
122   GtkTextLineSegment *seg;
123
124   seg = g_malloc(PIXMAP_SEG_SIZE);
125
126   seg->type = &gtk_text_pixmap_type;
127
128   seg->next = NULL;
129
130   seg->byte_count = 3; /* We convert to the 0xFFFD "unknown character",
131                           a 3-byte sequence in UTF-8 */
132   seg->char_count = 1;
133   
134   seg->body.pixmap.pixmap = pixmap;
135   seg->body.pixmap.mask = mask;
136
137   if (pixmap)
138     gdk_pixmap_ref(pixmap);
139
140   if (mask)
141     gdk_bitmap_ref(mask);
142   
143   return seg;
144 }
145
146 #if 0
147
148 /*
149  * The following structure is the official type record for the
150  * embedded window geometry manager:
151  */
152
153 static void             EmbWinRequestFunc _ANSI_ARGS_((gpointer clientData,
154                             Tk_Window tkwin));
155 static void             EmbWinLostSlaveFunc _ANSI_ARGS_((gpointer clientData,
156                             Tk_Window tkwin));
157
158 static Tk_GeomMgr textGeomType = {
159     "text",                     /* name */
160     EmbWinRequestFunc,          /* requestFunc */
161     EmbWinLostSlaveFunc,        /* lostSlaveFunc */
162 };
163
164 /*
165  * Definitions for alignment values:
166  */
167
168 #define ALIGN_BOTTOM            0
169 #define ALIGN_CENTER            1
170 #define ALIGN_TOP               2
171 #define ALIGN_BASELINE          3
172
173 /*
174  * Macro that determines the size of an embedded window segment:
175  */
176
177 #define EW_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET(GtkTextLineSegment, body) \
178         + sizeof(GtkTextEmbWindow)))
179
180 /*
181  * Prototypes for procedures defined in this file:
182  */
183
184 static int              AlignParseFunc _ANSI_ARGS_((gpointer clientData,
185                             Tcl_Interp *interp, Tk_Window tkwin, char *value,
186                             char *widgRec, int offset));
187 static char *           AlignPrintFunc _ANSI_ARGS_((gpointer clientData,
188                             Tk_Window tkwin, char *widgRec, int offset,
189                             Tcl_FreeFunc **freeFuncPtr));
190 static GtkTextLineSegment *     EmbWinCleanupFunc _ANSI_ARGS_((GtkTextLineSegment *segPtr,
191                             GtkTextLine *line));
192 static void             EmbWinCheckFunc _ANSI_ARGS_((GtkTextLineSegment *segPtr,
193                             GtkTextLine *line));
194 static void             EmbWinBboxFunc _ANSI_ARGS_((GtkTextDisplayChunk *chunkPtr,
195                             int index, int y, int lineHeight, int baseline,
196                             int *xPtr, int *yPtr, int *widthPtr,
197                             int *heightPtr));
198 static int              EmbWinConfigure _ANSI_ARGS_((GtkTextView *tkxt,
199                             GtkTextLineSegment *ewPtr, int argc, char **argv));
200 static void             EmbWinDelayedUnmap _ANSI_ARGS_((
201                             gpointer clientData));
202 static int              EmbWinDeleteFunc _ANSI_ARGS_((GtkTextLineSegment *segPtr,
203                             GtkTextLine *line, int treeGone));
204 static void             EmbWinDisplayFunc _ANSI_ARGS_((
205                             GtkTextDisplayChunk *chunkPtr, int x, int y,
206                             int lineHeight, int baseline, Display *display,
207                             Drawable dst, int screenY));
208 static int              EmbWinLayoutFunc _ANSI_ARGS_((GtkTextView *tkxt,
209                             GtkTextIndex *indexPtr, GtkTextLineSegment *segPtr,
210                             int offset, int maxX, int maxChars,
211                             int noCharsYet, GtkWrapMode wrapMode,
212                             GtkTextDisplayChunk *chunkPtr));
213 static void             EmbWinStructureFunc _ANSI_ARGS_((gpointer clientData,
214                             XEvent *eventPtr));
215 static void             EmbWinUndisplayFunc _ANSI_ARGS_((GtkTextView *tkxt,
216                             GtkTextDisplayChunk *chunkPtr));
217
218 /*
219  * The following structure declares the "embedded window" segment type.
220  */
221
222 static GtkTextLineSegmentClass tkTextEmbWindowType = {
223     "window",                                   /* name */
224     0,                                          /* leftGravity */
225     (GtkTextLineSegmentSplitFunc *) NULL,                       /* splitFunc */
226     EmbWinDeleteFunc,                           /* deleteFunc */
227     EmbWinCleanupFunc,                          /* cleanupFunc */
228     (GtkTextLineSegmentLineChangeFunc *) NULL,          /* lineChangeFunc */
229     EmbWinLayoutFunc,                           /* layoutFunc */
230     EmbWinCheckFunc                             /* checkFunc */
231 };
232
233 /*
234  * Information used for parsing window configuration options:
235  */
236
237 static Tk_CustomOption alignOption = {AlignParseFunc, AlignPrintFunc,
238         (gpointer) NULL};
239
240 static Tk_ConfigSpec configSpecs[] = {
241     {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
242         "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
243     {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,
244         (char *) NULL, G_STRUCT_OFFSET(GtkTextEmbWindow, create),
245         TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
246     {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,
247         "0", G_STRUCT_OFFSET(GtkTextEmbWindow, padX),
248         TK_CONFIG_DONT_SET_DEFAULT},
249     {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,
250         "0", G_STRUCT_OFFSET(GtkTextEmbWindow, padY),
251         TK_CONFIG_DONT_SET_DEFAULT},
252     {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
253         "0", G_STRUCT_OFFSET(GtkTextEmbWindow, stretch),
254         TK_CONFIG_DONT_SET_DEFAULT},
255     {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
256         (char *) NULL, G_STRUCT_OFFSET(GtkTextEmbWindow, tkwin),
257         TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
258     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
259         (char *) NULL, 0, 0}
260 };
261 \f
262 /*
263  *--------------------------------------------------------------
264  *
265  * GtkTextViewWindowCmd --
266  *
267  *      This procedure implements the "window" widget command
268  *      for text widgets.  See the user documentation for details
269  *      on what it does.
270  *
271  * Results:
272  *      A standard Tcl result or error.
273  *
274  * Side effects:
275  *      See the user documentation.
276  *
277  *--------------------------------------------------------------
278  */
279
280 int
281 GtkTextViewWindowCmd(tkxt, interp, argc, argv)
282     GtkTextView *tkxt;  /* Information about text widget. */
283     Tcl_Interp *interp;         /* Current interpreter. */
284     int argc;                   /* Number of arguments. */
285     char **argv;                /* Argument strings.  Someone else has already
286                                  * parsed this command enough to know that
287                                  * argv[1] is "window". */
288 {
289     size_t length;
290     GtkTextLineSegment *ewPtr;
291
292     if (argc < 3) {
293         Tcl_AppendResult(interp, "wrong # args: should be \"",
294                 argv[0], " window option ?arg arg ...?\"", (char *) NULL);
295         return TCL_ERROR;
296     }
297     length = strlen(argv[2]);
298     if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
299         GtkTextIndex index;
300         GtkTextLineSegment *ewPtr;
301
302         if (argc != 5) {
303             Tcl_AppendResult(interp, "wrong # args: should be \"",
304                     argv[0], " window cget index option\"",
305                     (char *) NULL);
306             return TCL_ERROR;
307         }
308         if (gtk_text_btree_index_from_string(interp, tkxt, argv[3], &index) != TCL_OK) {
309             return TCL_ERROR;
310         }
311         ewPtr = gtk_text_view_index_to_seg(&index, (int *) NULL);
312         if (ewPtr->type != &tkTextEmbWindowType) {
313             Tcl_AppendResult(interp, "no embedded window at index \"",
314                     argv[3], "\"", (char *) NULL);
315             return TCL_ERROR;
316         }
317         return Tk_ConfigureValue(interp, tkxt->tkwin, configSpecs,
318                 (char *) &ewPtr->body.ew, argv[4], 0);
319     } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
320         GtkTextIndex index;
321         GtkTextLineSegment *ewPtr;
322
323         if (argc < 4) {
324             Tcl_AppendResult(interp, "wrong # args: should be \"",
325                     argv[0], " window configure index ?option value ...?\"",
326                     (char *) NULL);
327             return TCL_ERROR;
328         }
329         if (gtk_text_btree_index_from_string(interp, tkxt, argv[3], &index) != TCL_OK) {
330             return TCL_ERROR;
331         }
332         ewPtr = gtk_text_view_index_to_seg(&index, (int *) NULL);
333         if (ewPtr->type != &tkTextEmbWindowType) {
334             Tcl_AppendResult(interp, "no embedded window at index \"",
335                     argv[3], "\"", (char *) NULL);
336             return TCL_ERROR;
337         }
338         if (argc == 4) {
339             return Tk_ConfigureInfo(interp, tkxt->tkwin, configSpecs,
340                     (char *) &ewPtr->body.ew, (char *) NULL, 0);
341         } else if (argc == 5) {
342             return Tk_ConfigureInfo(interp, tkxt->tkwin, configSpecs,
343                     (char *) &ewPtr->body.ew, argv[4], 0);
344         } else {
345             gtk_text_buffer_need_redisplay(tree->buffer, &index, &index);
346             return EmbWinConfigure(tkxt, ewPtr, argc-4, argv+4);
347         }
348     } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
349         GtkTextIndex index;
350         int lineIndex;
351
352         /*
353          * Add a new window.  Find where to put the new window, and
354          * mark that position for redisplay.
355          */
356
357         if (argc < 4) {
358             Tcl_AppendResult(interp, "wrong # args: should be \"",
359                     argv[0], " window create index ?option value ...?\"",
360                     (char *) NULL);
361             return TCL_ERROR;
362         }
363         if (gtk_text_btree_index_from_string(interp, tkxt, argv[3], &index) != TCL_OK) {
364             return TCL_ERROR;
365         }
366
367         /*
368          * Don't allow insertions on the last (dummy) line of the text.
369          */
370     
371         lineIndex = gtk_text_btree_line_number(index.line);
372         if (lineIndex == gtk_text_btree_num_lines(tkxt->tree)) {
373             lineIndex--;
374             gtk_text_btree_get_line_byte_index(tkxt->tree, lineIndex, G_MAXINT, &index);
375         }
376
377         /*
378          * Create the new window segment and initialize it.
379          */
380
381         ewPtr = (GtkTextLineSegment *) g_malloc(EW_SEG_SIZE);
382         ewPtr->type = &tkTextEmbWindowType;
383         ewPtr->size = 1;
384         ewPtr->body.ew.tkxt = tkxt;
385         ewPtr->body.ew.line = NULL;
386         ewPtr->body.ew.tkwin = NULL;
387         ewPtr->body.ew.create = NULL;
388         ewPtr->body.ew.align = ALIGN_CENTER;
389         ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
390         ewPtr->body.ew.stretch = 0;
391         ewPtr->body.ew.chunkCount = 0;
392         ewPtr->body.ew.displayed = 0;
393
394         /*
395          * Link the segment into the text widget, then configure it (delete
396          * it again if the configuration fails).
397          */
398
399         gtk_text_buffer_need_redisplay(tkxt, &index, &index);
400         gtk_text_btree_link_segment(ewPtr, &index);
401         if (EmbWinConfigure(tkxt, ewPtr, argc-4, argv+4) != TCL_OK) {
402             GtkTextIndex index2;
403
404             gtk_text_view_index_forw_chars(&index, 1, &index2);
405             gtk_text_btree_delete_chars(&index, &index2);
406             return TCL_ERROR;
407         }
408     } else if (strncmp(argv[2], "names", length) == 0) {
409         Tcl_HashSearch search;
410         Tcl_HashEntry *hPtr;
411
412         if (argc != 3) {
413             Tcl_AppendResult(interp, "wrong # args: should be \"",
414                     argv[0], " window names\"", (char *) NULL);
415             return TCL_ERROR;
416         }
417         for (hPtr = Tcl_FirstHashEntry(&tkxt->windowTable, &search);
418                 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
419             Tcl_AppendElement(interp,
420                     Tcl_GetHashKey(&tkxt->markTable, hPtr));
421         }
422     } else {
423         Tcl_AppendResult(interp, "bad window option \"", argv[2],
424                 "\": must be cget, configure, create, or names",
425                 (char *) NULL);
426         return TCL_ERROR;
427     }
428     return TCL_OK;
429 }
430 \f
431 /*
432  *--------------------------------------------------------------
433  *
434  * EmbWinConfigure --
435  *
436  *      This procedure is called to handle configuration options
437  *      for an embedded window, using an argc/argv list.
438  *
439  * Results:
440  *      The return value is a standard Tcl result.  If TCL_ERROR is
441  *      returned, then the interp's result contains an error message..
442  *
443  * Side effects:
444  *      Configuration information for the embedded window changes,
445  *      such as alignment, stretching, or name of the embedded
446  *      window.
447  *
448  *--------------------------------------------------------------
449  */
450
451 static int
452 EmbWinConfigure(tkxt, ewPtr, argc, argv)
453     GtkTextView *tkxt;          /* Information about text widget that
454                                  * contains embedded window. */
455     GtkTextLineSegment *ewPtr;  /* Embedded window to be configured. */
456     int argc;                   /* Number of strings in argv. */
457     char **argv;                /* Array of strings describing configuration
458                                  * options. */
459 {
460     Tk_Window oldWindow;
461     Tcl_HashEntry *hPtr;
462     int new;
463
464     oldWindow = ewPtr->body.ew.tkwin;
465     if (Tk_ConfigureWidget(tkxt->interp, tkxt->tkwin, configSpecs,
466             argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)
467             != TCL_OK) {
468         return TCL_ERROR;
469     }
470     if (oldWindow != ewPtr->body.ew.tkwin) {
471         if (oldWindow != NULL) {
472             Tcl_DeleteHashEntry(Tcl_FindHashEntry(&tkxt->windowTable,
473                     Tk_PathName(oldWindow)));
474             Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
475                     EmbWinStructureFunc, (gpointer) ewPtr);
476             Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
477                     (gpointer) NULL);
478             if (tkxt->tkwin != Tk_Parent(oldWindow)) {
479                 Tk_UnmaintainGeometry(oldWindow, tkxt->tkwin);
480             } else {
481                 Tk_UnmapWindow(oldWindow);
482             }
483         }
484         if (ewPtr->body.ew.tkwin != NULL) {
485             Tk_Window ancestor, parent;
486
487             /*
488              * Make sure that the text is either the parent of the
489              * embedded window or a descendant of that parent.  Also,
490              * don't allow a top-level window to be managed inside
491              * a text.
492              */
493
494             parent = Tk_Parent(ewPtr->body.ew.tkwin);
495             for (ancestor = tkxt->tkwin; ;
496                     ancestor = Tk_Parent(ancestor)) {
497                 if (ancestor == parent) {
498                     break;
499                 }
500                 if (Tk_IsTopLevel(ancestor)) {
501                     badMaster:
502                     Tcl_AppendResult(tkxt->interp, "can't embed ",
503                             Tk_PathName(ewPtr->body.ew.tkwin), " in ",
504                             Tk_PathName(tkxt->tkwin), (char *) NULL);
505                     ewPtr->body.ew.tkwin = NULL;
506                     return TCL_ERROR;
507                 }
508             }
509             if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
510                     || (ewPtr->body.ew.tkwin == tkxt->tkwin)) {
511                 goto badMaster;
512             }
513
514             /*
515              * Take over geometry management for the window, plus create
516              * an event handler to find out when it is deleted.
517              */
518
519             Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
520                     (gpointer) ewPtr);
521             Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
522                     EmbWinStructureFunc, (gpointer) ewPtr);
523
524             /*
525              * Special trick!  Must enter into the hash table *after*
526              * calling Tk_ManageGeometry:  if the window was already managed
527              * elsewhere in this text, the Tk_ManageGeometry call will cause
528              * the entry to be removed, which could potentially lose the new
529              * entry.
530              */
531
532             hPtr = Tcl_CreateHashEntry(&tkxt->windowTable,
533                     Tk_PathName(ewPtr->body.ew.tkwin), &new);
534             Tcl_SetHashValue(hPtr, ewPtr);
535
536         }
537     }
538     return TCL_OK;
539 }
540 \f
541 /*
542  *--------------------------------------------------------------
543  *
544  * AlignParseFunc --
545  *
546  *      This procedure is invoked by Tk_ConfigureWidget during
547  *      option processing to handle "-align" options for embedded
548  *      windows.
549  *
550  * Results:
551  *      A standard Tcl return value.
552  *
553  * Side effects:
554  *      The alignment for the embedded window may change.
555  *
556  *--------------------------------------------------------------
557  */
558
559         /* ARGSUSED */
560 static int
561 AlignParseFunc(clientData, interp, tkwin, value, widgRec, offset)
562     gpointer clientData;                /* Not used.*/
563     Tcl_Interp *interp;                 /* Used for reporting errors. */
564     Tk_Window tkwin;                    /* Window for text widget. */
565     char *value;                        /* Value of option. */
566     char *widgRec;                      /* Pointer to GtkTextEmbWindow
567                                          * structure. */
568     int offset;                         /* Offset into item (ignored). */
569 {
570     GtkTextEmbWindow *embPtr = (GtkTextEmbWindow *) widgRec;
571
572     if (strcmp(value, "baseline") == 0) {
573         embPtr->align = ALIGN_BASELINE;
574     } else if (strcmp(value, "bottom") == 0) {
575         embPtr->align = ALIGN_BOTTOM;
576     } else if (strcmp(value, "center") == 0) {
577         embPtr->align = ALIGN_CENTER;
578     } else if (strcmp(value, "top") == 0) {
579         embPtr->align = ALIGN_TOP;
580     } else {
581         Tcl_AppendResult(interp, "bad alignment \"", value,
582                 "\": must be baseline, bottom, center, or top",
583                 (char *) NULL);
584         return TCL_ERROR;
585     }
586     return TCL_OK;
587 }
588 \f
589 /*
590  *--------------------------------------------------------------
591  *
592  * AlignPrintFunc --
593  *
594  *      This procedure is invoked by the Tk configuration code
595  *      to produce a printable string for the "-align" configuration
596  *      option for embedded windows.
597  *
598  * Results:
599  *      The return value is a string describing the embedded
600  *      window's current alignment.
601  *
602  * Side effects:
603  *      None.
604  *
605  *--------------------------------------------------------------
606  */
607
608         /* ARGSUSED */
609 static char *
610 AlignPrintFunc(clientData, tkwin, widgRec, offset, freeFuncPtr)
611     gpointer clientData;                /* Ignored. */
612     Tk_Window tkwin;                    /* Window for text widget. */
613     char *widgRec;                      /* Pointer to GtkTextEmbWindow
614                                          * structure. */
615     int offset;                         /* Ignored. */
616     Tcl_FreeFunc **freeFuncPtr;         /* Pointer to variable to fill in with
617                                          * information about how to reclaim
618                                          * storage for return string. */
619 {
620     switch (((GtkTextEmbWindow *) widgRec)->align) {
621         case ALIGN_BASELINE:
622             return "baseline";
623         case ALIGN_BOTTOM:
624             return "bottom";
625         case ALIGN_CENTER:
626             return "center";
627         case ALIGN_TOP:
628             return "top";
629         default:
630             return "??";
631     }
632 }
633 \f
634 /*
635  *--------------------------------------------------------------
636  *
637  * EmbWinStructureFunc --
638  *
639  *      This procedure is invoked by the Tk event loop whenever
640  *      StructureNotify events occur for a window that's embedded
641  *      in a text widget.  This procedure's only purpose is to
642  *      clean up when windows are deleted.
643  *
644  * Results:
645  *      None.
646  *
647  * Side effects:
648  *      The window is disassociated from the window segment, and
649  *      the portion of the text is redisplayed.
650  *
651  *--------------------------------------------------------------
652  */
653
654 static void
655 EmbWinStructureFunc(clientData, eventPtr)
656     gpointer clientData;        /* Pointer to record describing window item. */
657     XEvent *eventPtr;           /* Describes what just happened. */
658 {
659     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) clientData;
660     GtkTextIndex index;
661
662     if (eventPtr->type != DestroyNotify) {
663         return;
664     }
665
666     Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.tkxt->windowTable,
667             Tk_PathName(ewPtr->body.ew.tkwin)));
668     ewPtr->body.ew.tkwin = NULL;
669     index.tree = ewPtr->body.ew.tkxt->tree;
670     index.line = ewPtr->body.ew.line;
671     index.byteIndex = gtk_text_line_segment_get_offset(ewPtr, ewPtr->body.ew.line);
672     gtk_text_buffer_need_redisplay(ewPtr->body.ew.tkxt, &index, &index);
673 }
674 \f
675 /*
676  *--------------------------------------------------------------
677  *
678  * EmbWinRequestFunc --
679  *
680  *      This procedure is invoked whenever a window that's associated
681  *      with a window canvas item changes its requested dimensions.
682  *
683  * Results:
684  *      None.
685  *
686  * Side effects:
687  *      The size and location on the screen of the window may change,
688  *      depending on the options specified for the window item.
689  *
690  *--------------------------------------------------------------
691  */
692
693         /* ARGSUSED */
694 static void
695 EmbWinRequestFunc(clientData, tkwin)
696     gpointer clientData;                /* Pointer to record for window item. */
697     Tk_Window tkwin;                    /* Window that changed its desired
698                                          * size. */
699 {
700     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) clientData;
701     GtkTextIndex index;
702
703     index.tree = ewPtr->body.ew.tkxt->tree;
704     index.line = ewPtr->body.ew.line;
705     index.byteIndex = gtk_text_line_segment_get_offset(ewPtr, ewPtr->body.ew.line);
706     gtk_text_buffer_need_redisplay(ewPtr->body.ew.tkxt, &index, &index);
707 }
708 \f
709 /*
710  *--------------------------------------------------------------
711  *
712  * EmbWinLostSlaveFunc --
713  *
714  *      This procedure is invoked by the Tk geometry manager when
715  *      a slave window managed by a text widget is claimed away
716  *      by another geometry manager.
717  *
718  * Results:
719  *      None.
720  *
721  * Side effects:
722  *      The window is disassociated from the window segment, and
723  *      the portion of the text is redisplayed.
724  *
725  *--------------------------------------------------------------
726  */
727
728 static void
729 EmbWinLostSlaveFunc(clientData, tkwin)
730     gpointer clientData;        /* Pointer to record describing window item. */
731     Tk_Window tkwin;            /* Window that was claimed away by another
732                                  * geometry manager. */
733 {
734     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) clientData;
735     GtkTextIndex index;
736
737     Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
738             EmbWinStructureFunc, (gpointer) ewPtr);
739     Tcl_CancelIdleCall(EmbWinDelayedUnmap, (gpointer) ewPtr);
740     if (ewPtr->body.ew.tkxt->tkwin != Tk_Parent(tkwin)) {
741         Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.tkxt->tkwin);
742     } else {
743         Tk_UnmapWindow(tkwin);
744     }
745     Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.tkxt->windowTable,
746             Tk_PathName(ewPtr->body.ew.tkwin)));
747     ewPtr->body.ew.tkwin = NULL;
748     index.tree = ewPtr->body.ew.tkxt->tree;
749     index.line = ewPtr->body.ew.line;
750     index.byteIndex = gtk_text_line_segment_get_offset(ewPtr, ewPtr->body.ew.line);
751     gtk_text_buffer_need_redisplay(ewPtr->body.ew.tkxt, &index, &index);
752 }
753 \f
754 /*
755  *--------------------------------------------------------------
756  *
757  * EmbWinDeleteFunc --
758  *
759  *      This procedure is invoked by the text B-tree code whenever
760  *      an embedded window lies in a range of characters being deleted.
761  *
762  * Results:
763  *      Returns 0 to indicate that the deletion has been accepted.
764  *
765  * Side effects:
766  *      The embedded window is deleted, if it exists, and any resources
767  *      associated with it are released.
768  *
769  *--------------------------------------------------------------
770  */
771
772         /* ARGSUSED */
773 static int
774 EmbWinDeleteFunc(ewPtr, line, treeGone)
775     GtkTextLineSegment *ewPtr;          /* Segment being deleted. */
776     GtkTextLine *line;          /* Line containing segment. */
777     int treeGone;                       /* Non-zero means the entire tree is
778                                          * being deleted, so everything must
779                                          * get cleaned up. */
780 {
781     Tcl_HashEntry *hPtr;
782
783     if (ewPtr->body.ew.tkwin != NULL) {
784         hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.tkxt->windowTable,
785                 Tk_PathName(ewPtr->body.ew.tkwin));
786         if (hPtr != NULL) {
787             /*
788              * (It's possible for there to be no hash table entry for this
789              * window, if an error occurred while creating the window segment
790              * but before the window got added to the table)
791              */
792
793             Tcl_DeleteHashEntry(hPtr);
794         }
795
796         /*
797          * Delete the event handler for the window before destroying
798          * the window, so that EmbWinStructureFunc doesn't get called
799          * (we'll already do everything that it would have done, and
800          * it will just get confused).
801          */
802
803         Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
804                 EmbWinStructureFunc, (gpointer) ewPtr);
805         Tk_DestroyWindow(ewPtr->body.ew.tkwin);
806     }
807     Tcl_CancelIdleCall(EmbWinDelayedUnmap, (gpointer) ewPtr);
808     Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,
809             ewPtr->body.ew.tkxt->display, 0);
810     g_free((char *) ewPtr);
811     return 0;
812 }
813 \f
814 /*
815  *--------------------------------------------------------------
816  *
817  * EmbWinCleanupFunc --
818  *
819  *      This procedure is invoked by the B-tree code whenever a
820  *      segment containing an embedded window is moved from one
821  *      line to another.
822  *
823  * Results:
824  *      None.
825  *
826  * Side effects:
827  *      The line field of the segment gets updated.
828  *
829  *--------------------------------------------------------------
830  */
831
832 static GtkTextLineSegment *
833 EmbWinCleanupFunc(ewPtr, line)
834     GtkTextLineSegment *ewPtr;          /* Mark segment that's being moved. */
835     GtkTextLine *line;          /* Line that now contains segment. */
836 {
837     ewPtr->body.ew.line = line;
838     return ewPtr;
839 }
840 \f
841 /*
842  *--------------------------------------------------------------
843  *
844  * EmbWinLayoutFunc --
845  *
846  *      This procedure is the "layoutFunc" for embedded window
847  *      segments.
848  *
849  * Results:
850  *      1 is returned to indicate that the segment should be
851  *      displayed.  The chunkPtr structure is filled in.
852  *
853  * Side effects:
854  *      None, except for filling in chunkPtr.
855  *
856  *--------------------------------------------------------------
857  */
858
859         /*ARGSUSED*/
860 static int
861 EmbWinLayoutFunc(tkxt, indexPtr, ewPtr, offset, maxX, maxChars,
862         noCharsYet, wrapMode, chunkPtr)
863     GtkTextView *tkxt;          /* Text widget being layed out. */
864     GtkTextIndex *indexPtr;     /* Identifies first character in chunk. */
865     GtkTextLineSegment *ewPtr;  /* Segment corresponding to indexPtr. */
866     int offset;                 /* Offset within segPtr corresponding to
867                                  * indexPtr (always 0). */
868     int maxX;                   /* Chunk must not occupy pixels at this
869                                  * position or higher. */
870     int maxChars;               /* Chunk must not include more than this
871                                  * many characters. */
872     int noCharsYet;             /* Non-zero means no characters have been
873                                  * assigned to this line yet. */
874     GtkWrapMode wrapMode;       /* Wrap mode to use for line: GTK_WRAPMODE_CHAR,
875                                  * GTK_WRAPMODE_NONE, or GTK_WRAPMODE_WORD. */
876     GtkTextDisplayChunk *chunkPtr;
877                                 /* Structure to fill in with information
878                                  * about this chunk.  The x field has already
879                                  * been set by the caller. */
880 {
881     int width, height;
882
883     if (offset != 0) {
884         panic("Non-zero offset in EmbWinLayoutFunc");
885     }
886
887     if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
888         int code, new;
889         Tcl_DString name;
890         Tk_Window ancestor;
891         Tcl_HashEntry *hPtr;
892
893         /*
894          * The window doesn't currently exist.  Create it by evaluating
895          * the creation script.  The script must return the window's
896          * path name:  look up that name to get back to the window
897          * token.  Then ourselves as the geometry manager for
898          * the window.
899          */
900
901         code = Tcl_GlobalEval(tkxt->interp, ewPtr->body.ew.create);
902         if (code != TCL_OK) {
903             createError:
904             Tcl_BackgroundError(tkxt->interp);
905             goto gotWindow;
906         }
907         Tcl_DStringInit(&name);
908         Tcl_DStringAppend(&name, Tcl_GetStringResult(tkxt->interp), -1);
909         Tcl_ResetResult(tkxt->interp);
910         ewPtr->body.ew.tkwin = Tk_NameToWindow(tkxt->interp,
911                 Tcl_DStringValue(&name), tkxt->tkwin);
912         if (ewPtr->body.ew.tkwin == NULL) {
913             goto createError;
914         }
915         for (ancestor = tkxt->tkwin; ;
916                 ancestor = Tk_Parent(ancestor)) {
917             if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
918                 break;
919             }
920             if (Tk_IsTopLevel(ancestor)) {
921                 badMaster:
922                 Tcl_AppendResult(tkxt->interp, "can't embed ",
923                         Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",
924                         Tk_PathName(tkxt->tkwin), (char *) NULL);
925                 Tcl_BackgroundError(tkxt->interp);
926                 ewPtr->body.ew.tkwin = NULL;
927                 goto gotWindow;
928             }
929         }
930         if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
931                 || (tkxt->tkwin == ewPtr->body.ew.tkwin)) {
932             goto badMaster;
933         }
934         Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
935                 (gpointer) ewPtr);
936         Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
937                 EmbWinStructureFunc, (gpointer) ewPtr);
938
939         /*
940          * Special trick!  Must enter into the hash table *after*
941          * calling Tk_ManageGeometry:  if the window was already managed
942          * elsewhere in this text, the Tk_ManageGeometry call will cause
943          * the entry to be removed, which could potentially lose the new
944          * entry.
945          */
946
947         hPtr = Tcl_CreateHashEntry(&tkxt->windowTable,
948                 Tk_PathName(ewPtr->body.ew.tkwin), &new);
949         Tcl_SetHashValue(hPtr, ewPtr);
950     }
951
952     /*
953      * See if there's room for this window on this line.
954      */
955
956     gotWindow:
957     if (ewPtr->body.ew.tkwin == NULL) {
958         width = 0;
959         height = 0;
960     } else {
961         width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;
962         height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
963     }
964     if ((width > (maxX - chunkPtr->x))
965             && !noCharsYet && (tkxt->wrapMode != GTK_WRAPMODE_NONE)) {
966         return 0;
967     }
968
969     /*
970      * Fill in the chunk structure.
971      */
972
973     chunkPtr->displayFunc = EmbWinDisplayFunc;
974     chunkPtr->undisplayFunc = EmbWinUndisplayFunc;
975     chunkPtr->measureFunc = (GtkTextViewChunkMeasureFunc *) NULL;
976     chunkPtr->bboxFunc = EmbWinBboxFunc;
977     chunkPtr->numBytes = 1;
978     if (ewPtr->body.ew.align == ALIGN_BASELINE) {
979         chunkPtr->minAscent = height - ewPtr->body.ew.padY;
980         chunkPtr->minDescent = ewPtr->body.ew.padY;
981         chunkPtr->minHeight = 0;
982     } else {
983         chunkPtr->minAscent = 0;
984         chunkPtr->minDescent = 0;
985         chunkPtr->minHeight = height;
986     }
987     chunkPtr->width = width;
988     chunkPtr->breakIndex = -1;
989     chunkPtr->breakIndex = 1;
990     chunkPtr->clientData = (gpointer) ewPtr;
991     ewPtr->body.ew.chunkCount += 1;
992     return 1;
993 }
994 \f
995 /*
996  *--------------------------------------------------------------
997  *
998  * EmbWinCheckFunc --
999  *
1000  *      This procedure is invoked by the B-tree code to perform
1001  *      consistency checks on embedded windows.
1002  *
1003  * Results:
1004  *      None.
1005  *
1006  * Side effects:
1007  *      The procedure panics if it detects anything wrong with
1008  *      the embedded window.
1009  *
1010  *--------------------------------------------------------------
1011  */
1012
1013 static void
1014 EmbWinCheckFunc(ewPtr, line)
1015     GtkTextLineSegment *ewPtr;          /* Segment to check. */
1016     GtkTextLine *line;          /* Line containing segment. */
1017 {
1018     if (ewPtr->next == NULL) {
1019         panic("EmbWinCheckFunc: embedded window is last segment in line");
1020     }
1021     if (ewPtr->size != 1) {
1022         panic("EmbWinCheckFunc: embedded window has size %d", ewPtr->size);
1023     }
1024 }
1025 \f
1026 /*
1027  *--------------------------------------------------------------
1028  *
1029  * EmbWinDisplayFunc --
1030  *
1031  *      This procedure is invoked by the text displaying code
1032  *      when it is time to actually draw an embedded window
1033  *      chunk on the screen.
1034  *
1035  * Results:
1036  *      None.
1037  *
1038  * Side effects:
1039  *      The embedded window gets moved to the correct location
1040  *      and mapped onto the screen.
1041  *
1042  *--------------------------------------------------------------
1043  */
1044
1045 static void
1046 EmbWinDisplayFunc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
1047     GtkTextDisplayChunk *chunkPtr;              /* Chunk that is to be drawn. */
1048     int x;                              /* X-position in dst at which to
1049                                          * draw this chunk (differs from
1050                                          * the x-position in the chunk because
1051                                          * of scrolling). */
1052     int y;                              /* Top of rectangular bounding box
1053                                          * for line: tells where to draw this
1054                                          * chunk in dst (x-position is in
1055                                          * the chunk itself). */
1056     int lineHeight;                     /* Total height of line. */
1057     int baseline;                       /* Offset of baseline from y. */
1058     Display *display;                   /* Display to use for drawing. */
1059     Drawable dst;                       /* Pixmap or window in which to draw */
1060     int screenY;                        /* Y-coordinate in text window that
1061                                          * corresponds to y. */
1062 {
1063     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) chunkPtr->clientData;
1064     int lineX, windowX, windowY, width, height;
1065     Tk_Window tkwin;
1066
1067     tkwin = ewPtr->body.ew.tkwin;
1068     if (tkwin == NULL) {
1069         return;
1070     }
1071     if ((x + chunkPtr->width) <= 0) {
1072         /*
1073          * The window is off-screen;  just unmap it.
1074          */
1075
1076         if (ewPtr->body.ew.tkxt->tkwin != Tk_Parent(tkwin)) {
1077             Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.tkxt->tkwin);
1078         } else {
1079             Tk_UnmapWindow(tkwin);
1080         }
1081         return;
1082     }
1083
1084     /*
1085      * Compute the window's location and size in the text widget, taking
1086      * into account the align and stretch values for the window.
1087      */
1088
1089     EmbWinBboxFunc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX,
1090             &windowY, &width, &height);
1091     windowX = lineX - chunkPtr->x + x;
1092
1093     if (ewPtr->body.ew.tkxt->tkwin == Tk_Parent(tkwin)) {
1094         if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
1095                 || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
1096                 || (height != Tk_Height(tkwin))) {
1097             Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
1098         }
1099         Tk_MapWindow(tkwin);
1100     } else {
1101         Tk_MaintainGeometry(tkwin, ewPtr->body.ew.tkxt->tkwin,
1102                 windowX, windowY, width, height);
1103     }
1104
1105     /*
1106      * Mark the window as displayed so that it won't get unmapped.
1107      */
1108
1109     ewPtr->body.ew.displayed = 1;
1110 }
1111 \f
1112 /*
1113  *--------------------------------------------------------------
1114  *
1115  * EmbWinUndisplayFunc --
1116  *
1117  *      This procedure is called when the chunk for an embedded
1118  *      window is no longer going to be displayed.  It arranges
1119  *      for the window associated with the chunk to be unmapped.
1120  *
1121  * Results:
1122  *      None.
1123  *
1124  * Side effects:
1125  *      The window is scheduled for unmapping.
1126  *
1127  *--------------------------------------------------------------
1128  */
1129
1130 static void
1131 EmbWinUndisplayFunc(tkxt, chunkPtr)
1132     GtkTextView *tkxt;                  /* Overall information about text
1133                                          * widget. */
1134     GtkTextDisplayChunk *chunkPtr;              /* Chunk that is about to be freed. */
1135 {
1136     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) chunkPtr->clientData;
1137
1138     ewPtr->body.ew.chunkCount--;
1139     if (ewPtr->body.ew.chunkCount == 0) {
1140         /*
1141          * Don't unmap the window immediately, since there's a good chance
1142          * that it will immediately be redisplayed, perhaps even in the
1143          * same place.  Instead, schedule the window to be unmapped later;
1144          * the call to EmbWinDelayedUnmap will be cancelled in the likely
1145          * event that the unmap becomes unnecessary.
1146          */
1147
1148         ewPtr->body.ew.displayed = 0;
1149         Tcl_DoWhenIdle(EmbWinDelayedUnmap, (gpointer) ewPtr);
1150     }
1151 }
1152 \f
1153 /*
1154  *--------------------------------------------------------------
1155  *
1156  * EmbWinBboxFunc --
1157  *
1158  *      This procedure is called to compute the bounding box of
1159  *      the area occupied by an embedded window.
1160  *
1161  * Results:
1162  *      There is no return value.  *xPtr and *yPtr are filled in
1163  *      with the coordinates of the upper left corner of the
1164  *      window, and *widthPtr and *heightPtr are filled in with
1165  *      the dimensions of the window in pixels.  Note:  not all
1166  *      of the returned bbox is necessarily visible on the screen
1167  *      (the rightmost part might be off-screen to the right,
1168  *      and the bottommost part might be off-screen to the bottom).
1169  *
1170  * Side effects:
1171  *      None.
1172  *
1173  *--------------------------------------------------------------
1174  */
1175
1176 static void
1177 EmbWinBboxFunc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
1178         widthPtr, heightPtr)
1179     GtkTextDisplayChunk *chunkPtr;              /* Chunk containing desired char. */
1180     int index;                          /* Index of desired character within
1181                                          * the chunk. */
1182     int y;                              /* Topmost pixel in area allocated
1183                                          * for this line. */
1184     int lineHeight;                     /* Total height of line. */
1185     int baseline;                       /* Location of line's baseline, in
1186                                          * pixels measured down from y. */
1187     int *xPtr, *yPtr;                   /* Gets filled in with coords of
1188                                          * character's upper-left pixel. */
1189     int *widthPtr;                      /* Gets filled in with width of
1190                                          * character, in pixels. */
1191     int *heightPtr;                     /* Gets filled in with height of
1192                                          * character, in pixels. */
1193 {
1194     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) chunkPtr->clientData;
1195     Tk_Window tkwin;
1196
1197     tkwin = ewPtr->body.ew.tkwin;
1198     if (tkwin != NULL) {
1199         *widthPtr = Tk_ReqWidth(tkwin);
1200         *heightPtr = Tk_ReqHeight(tkwin);
1201     } else {
1202         *widthPtr = 0;
1203         *heightPtr = 0;
1204     }
1205     *xPtr = chunkPtr->x + ewPtr->body.ew.padX;
1206     if (ewPtr->body.ew.stretch) {
1207         if (ewPtr->body.ew.align == ALIGN_BASELINE) {
1208             *heightPtr = baseline - ewPtr->body.ew.padY;
1209         } else {
1210             *heightPtr = lineHeight - 2*ewPtr->body.ew.padY;
1211         }
1212     }
1213     switch (ewPtr->body.ew.align) {
1214         case ALIGN_BOTTOM:
1215             *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
1216             break;
1217         case ALIGN_CENTER:
1218             *yPtr = y + (lineHeight - *heightPtr)/2;
1219             break;
1220         case ALIGN_TOP:
1221             *yPtr = y + ewPtr->body.ew.padY;
1222             break;
1223         case ALIGN_BASELINE:
1224             *yPtr = y + (baseline - *heightPtr);
1225             break;
1226     }
1227 }
1228 \f
1229 /*
1230  *--------------------------------------------------------------
1231  *
1232  * EmbWinDelayedUnmap --
1233  *
1234  *      This procedure is an idle handler that does the actual
1235  *      work of unmapping an embedded window.  See the comment
1236  *      in EmbWinUndisplayFunc for details.
1237  *
1238  * Results:
1239  *      None.
1240  *
1241  * Side effects:
1242  *      The window gets unmapped, unless its chunk reference count
1243  *      has become non-zero again.
1244  *
1245  *--------------------------------------------------------------
1246  */
1247
1248 static void
1249 EmbWinDelayedUnmap(clientData)
1250     gpointer clientData;                /* Token for the window to
1251                                          * be unmapped. */
1252 {
1253     GtkTextLineSegment *ewPtr = (GtkTextLineSegment *) clientData;
1254
1255     if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) {
1256         if (ewPtr->body.ew.tkxt->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) {
1257             Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin,
1258                     ewPtr->body.ew.tkxt->tkwin);
1259         } else {
1260             Tk_UnmapWindow(ewPtr->body.ew.tkwin);
1261         }
1262     }
1263 }
1264 \f
1265 /*
1266  *--------------------------------------------------------------
1267  *
1268  * GtkTextViewWindowIndex --
1269  *
1270  *      Given the name of an embedded window within a text widget,
1271  *      returns an index corresponding to the window's position
1272  *      in the text.
1273  *
1274  * Results:
1275  *      The return value is 1 if there is an embedded window by
1276  *      the given name in the text widget, 0 otherwise.  If the
1277  *      window exists, *indexPtr is filled in with its index.
1278  *
1279  * Side effects:
1280  *      None.
1281  *
1282  *--------------------------------------------------------------
1283  */
1284
1285 int
1286 GtkTextViewWindowIndex(tkxt, name, indexPtr)
1287     GtkTextView *tkxt;          /* Text widget containing window. */
1288     char *name;                 /* Name of window. */
1289     GtkTextIndex *indexPtr;     /* Index information gets stored here. */
1290 {
1291     Tcl_HashEntry *hPtr;
1292     GtkTextLineSegment *ewPtr;
1293
1294     hPtr = Tcl_FindHashEntry(&tkxt->windowTable, name);
1295     if (hPtr == NULL) {
1296         return 0;
1297     }
1298     ewPtr = (GtkTextLineSegment *) Tcl_GetHashValue(hPtr);
1299     indexPtr->tree = tkxt->tree;
1300     indexPtr->line = ewPtr->body.ew.line;
1301     indexPtr->byteIndex = gtk_text_line_segment_get_offset(ewPtr, indexPtr->line);
1302     return 1;
1303 }
1304 #endif