home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / generic / tkTextWind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  35.3 KB  |  1,210 lines

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