/* PanedSize -- * Compute the requested size of the paned widget * from the individual pane request sizes. * * Used as the WidgetSpec sizeProc and the ManagerSpec sizeProc. */ static int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr) { Paned *pw = recordPtr; int nPanes = Ttk_NumberSlaves(pw->paned.mgr); int nSashes = nPanes - 1; int sashThickness = pw->paned.sashThickness; int width = 0, height = 0; int index; if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) { for (index = 0; index < nPanes; ++index) { Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index); if (height < Tk_ReqHeight(slaveWindow)) height = Tk_ReqHeight(slaveWindow); width += pane->reqSize; } width += nSashes * sashThickness; } else { for (index = 0; index < nPanes; ++index) { Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index); if (width < Tk_ReqWidth(slaveWindow)) width = Tk_ReqWidth(slaveWindow); height += pane->reqSize; } height += nSashes * sashThickness; } *widthPtr = pw->paned.width > 0 ? pw->paned.width : width; *heightPtr = pw->paned.height > 0 ? pw->paned.height : height; return 1; }
/* ** zWin is the name of a child widget that is used to implement an ** input element. Query Tk for information about this widget (such ** as its size) and put that information in the pElem structure ** that represents the input. */ static void SizeAndLink(HtmlWidget *htmlPtr, char *zWin, HtmlElement *pElem){ pElem->input.tkwin = Tk_NameToWindow(htmlPtr->interp, zWin, htmlPtr->clipwin); if( pElem->input.tkwin==0 ){ Tcl_ResetResult(htmlPtr->interp); EmptyInput(pElem); }else if( pElem->input.type==INPUT_TYPE_Hidden ){ pElem->input.w = 0; pElem->input.h = 0; pElem->base.flags &= !HTML_Visible; pElem->base.style.flags |= STY_Invisible; }else{ pElem->input.w = Tk_ReqWidth(pElem->input.tkwin); pElem->input.h = Tk_ReqHeight(pElem->input.tkwin); pElem->base.flags |= HTML_Visible; pElem->input.htmlPtr = htmlPtr; Tk_ManageGeometry(pElem->input.tkwin, &htmlGeomType, pElem); Tk_CreateEventHandler(pElem->input.tkwin, StructureNotifyMask, HtmlInputEventProc, pElem); } pElem->input.pNext = 0; if( htmlPtr->firstInput==0 ){ htmlPtr->firstInput = pElem; }else{ htmlPtr->lastInput->input.pNext = pElem; } htmlPtr->lastInput = pElem; pElem->input.sized = 1; }
static void EmbWinBboxProc( TkText *textPtr, /* Information about text widget. */ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */ int index, /* Index of desired character within the * chunk. */ int y, /* Topmost pixel in area allocated for this * line. */ int lineHeight, /* Total height of line. */ int baseline, /* Location of line's baseline, in pixels * measured down from y. */ int *xPtr, int *yPtr, /* Gets filled in with coords of character's * upper-left pixel. */ int *widthPtr, /* Gets filled in with width of window, in * pixels. */ int *heightPtr) /* Gets filled in with height of window, in * pixels. */ { Tk_Window tkwin; TkTextSegment *ewPtr = chunkPtr->clientData; TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr); if (client == NULL) { tkwin = NULL; } else { tkwin = client->tkwin; } if (tkwin != NULL) { *widthPtr = Tk_ReqWidth(tkwin); *heightPtr = Tk_ReqHeight(tkwin); } else { *widthPtr = 0; *heightPtr = 0; } *xPtr = chunkPtr->x + ewPtr->body.ew.padX; if (ewPtr->body.ew.stretch) { if (ewPtr->body.ew.align == ALIGN_BASELINE) { *heightPtr = baseline - ewPtr->body.ew.padY; } else { *heightPtr = lineHeight - 2*ewPtr->body.ew.padY; } } switch (ewPtr->body.ew.align) { case ALIGN_BOTTOM: *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY); break; case ALIGN_CENTER: *yPtr = y + (lineHeight - *heightPtr)/2; break; case ALIGN_TOP: *yPtr = y + ewPtr->body.ew.padY; break; case ALIGN_BASELINE: *yPtr = y + (baseline - *heightPtr); break; } }
/* ** This routine is called when one of the child windows for a form ** wants to change its size. */ static void HtmlInputRequestProc(ClientData clientData, Tk_Window tkwin){ HtmlElement *pElem = (HtmlElement*)clientData; if( pElem->base.type!=Html_INPUT ){ CANT_HAPPEN; return; } if( pElem->input.tkwin!=tkwin ){ CANT_HAPPEN; return; } pElem->input.w = Tk_ReqWidth(tkwin); pElem->input.h = Tk_ReqHeight(tkwin); if( pElem->input.htmlPtr && pElem->input.htmlPtr->tkwin!=0 ){ pElem->input.htmlPtr->flags |= RELAYOUT; HtmlScheduleRedraw(pElem->input.htmlPtr); } }
void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window slaveWindow) { Ttk_Manager *mgr = clientData; int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow); int reqWidth = Tk_ReqWidth(slaveWindow); int reqHeight= Tk_ReqHeight(slaveWindow); if (mgr->managerSpec->SlaveRequest( mgr->managerData, slaveIndex, reqWidth, reqHeight)) { ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); } }
/* LabelframeLabelSize -- * Extract the requested width and height of the labelframe's label: * taken from the label widget if specified, otherwise the text label. */ static void LabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr) { Tk_Window labelWidget = lframePtr->label.labelWidget; Ttk_Layout labelLayout = lframePtr->label.labelLayout; if (labelWidget) { *widthPtr = Tk_ReqWidth(labelWidget); *heightPtr = Tk_ReqHeight(labelWidget); } else if (labelLayout) { Ttk_LayoutSize(labelLayout, 0, widthPtr, heightPtr); } else { *widthPtr = *heightPtr = 0; } }
/* CreatePane -- * Create a new pane record. */ static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window slaveWindow) { Tk_OptionTable optionTable = pw->paned.paneOptionTable; void *record = ckalloc(sizeof(Pane)); Pane *pane = record; memset(record, 0, sizeof(Pane)); if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) { ckfree(record); return NULL; } pane->reqSize = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow); return pane; }
static void RecomputePlacement( ClientData clientData) /* Pointer to Master record. */ { register Master *masterPtr = clientData; register Slave *slavePtr; int x, y, width, height, tmp; int masterWidth, masterHeight, masterX, masterY; double x1, y1, x2, y2; int abort; /* May get set to non-zero to abort this * placement operation. */ masterPtr->flags &= ~PARENT_RECONFIG_PENDING; /* * Abort any nested call to RecomputePlacement for this window, since * we'll do everything necessary here, and set up so this call can be * aborted if necessary. */ if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } masterPtr->abortPtr = &abort; abort = 0; Tcl_Preserve(masterPtr); /* * Iterate over all the slaves for the master. Each slave's geometry can * be computed independently of the other slaves. Changes to the window's * structure could cause almost anything to happen, including deleting the * parent or child. If this happens, we'll be told to abort. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; slavePtr = slavePtr->nextPtr) { /* * Step 1: compute size and borderwidth of master, taking into account * desired border mode. */ masterX = masterY = 0; masterWidth = Tk_Width(masterPtr->tkwin); masterHeight = Tk_Height(masterPtr->tkwin); if (slavePtr->borderMode == BM_INSIDE) { masterX = Tk_InternalBorderLeft(masterPtr->tkwin); masterY = Tk_InternalBorderTop(masterPtr->tkwin); masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin); masterHeight -= masterY + Tk_InternalBorderBottom(masterPtr->tkwin); } else if (slavePtr->borderMode == BM_OUTSIDE) { masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width; masterWidth -= 2 * masterX; masterHeight -= 2 * masterY; } /* * Step 2: compute size of slave (outside dimensions including border) * and location of anchor point within master. */ x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth); x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5)); y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight); y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5)); if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) { width = 0; if (slavePtr->flags & CHILD_WIDTH) { width += slavePtr->width; } if (slavePtr->flags & CHILD_REL_WIDTH) { /* * The code below is a bit tricky. In order to round correctly * when both relX and relWidth are specified, compute the * location of the right edge and round that, then compute * width. If we compute the width and round it, rounding * errors in relX and relWidth accumulate. */ x2 = x1 + (slavePtr->relWidth*masterWidth); tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5)); width += tmp - x; } } else { width = Tk_ReqWidth(slavePtr->tkwin) + 2*Tk_Changes(slavePtr->tkwin)->border_width; } if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) { height = 0; if (slavePtr->flags & CHILD_HEIGHT) { height += slavePtr->height; } if (slavePtr->flags & CHILD_REL_HEIGHT) { /* * See note above for rounding errors in width computation. */ y2 = y1 + (slavePtr->relHeight*masterHeight); tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5)); height += tmp - y; } } else { height = Tk_ReqHeight(slavePtr->tkwin) + 2*Tk_Changes(slavePtr->tkwin)->border_width; } /* * Step 3: adjust the x and y positions so that the desired anchor * point on the slave appears at that position. Also adjust for the * border mode and master's border. */ switch (slavePtr->anchor) { case TK_ANCHOR_N: x -= width/2; break; case TK_ANCHOR_NE: x -= width; break; case TK_ANCHOR_E: x -= width; y -= height/2; break; case TK_ANCHOR_SE: x -= width; y -= height; break; case TK_ANCHOR_S: x -= width/2; y -= height; break; case TK_ANCHOR_SW: y -= height; break; case TK_ANCHOR_W: y -= height/2; break; case TK_ANCHOR_NW: break; case TK_ANCHOR_CENTER: x -= width/2; y -= height/2; break; } /* * Step 4: adjust width and height again to reflect inside dimensions * of window rather than outside. Also make sure that the width and * height aren't zero. */ width -= 2*Tk_Changes(slavePtr->tkwin)->border_width; height -= 2*Tk_Changes(slavePtr->tkwin)->border_width; if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } /* * Step 5: reconfigure the window and map it if needed. If the slave * is a child of the master, we do this ourselves. If the slave isn't * a child of the master, let Tk_MaintainGeometry do the work (it will * re-adjust things as relevant windows map, unmap, and move). */ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { if ((x != Tk_X(slavePtr->tkwin)) || (y != Tk_Y(slavePtr->tkwin)) || (width != Tk_Width(slavePtr->tkwin)) || (height != Tk_Height(slavePtr->tkwin))) { Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); } if (abort) { break; } /* * Don't map the slave unless the master is mapped: the slave will * get mapped later, when the master is mapped. */ if (Tk_IsMapped(masterPtr->tkwin)) { Tk_MapWindow(slavePtr->tkwin); } } else { if ((width <= 0) || (height <= 0)) { Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); Tk_UnmapWindow(slavePtr->tkwin); } else { Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y, width, height); } } } masterPtr->abortPtr = NULL; Tcl_Release(masterPtr); }
/*ARGSUSED*/ static int EmbWinLayoutProc( TkText *textPtr, /* Text widget being layed out. */ TkTextIndex *indexPtr, /* Identifies first character in chunk. */ TkTextSegment *ewPtr, /* Segment corresponding to indexPtr. */ int offset, /* Offset within segPtr corresponding to * indexPtr (always 0). */ int maxX, /* Chunk must not occupy pixels at this * position or higher. */ int maxChars, /* Chunk must not include more than this many * characters. */ int noCharsYet, /* Non-zero means no characters have been * assigned to this line yet. */ TkWrapMode wrapMode, /* Wrap mode to use for line: * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or * TEXT_WRAPMODE_WORD. */ register TkTextDispChunk *chunkPtr) /* Structure to fill in with information about * this chunk. The x field has already been * set by the caller. */ { int width, height; TkTextEmbWindowClient *client; if (offset != 0) { Tcl_Panic("Non-zero offset in EmbWinLayoutProc"); } client = EmbWinGetClient(textPtr, ewPtr); if (client == NULL) { ewPtr->body.ew.tkwin = NULL; } else { ewPtr->body.ew.tkwin = client->tkwin; } if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) { int code, isNew; Tk_Window ancestor; Tcl_HashEntry *hPtr; const char *before, *string; Tcl_DString name, buf, *dsPtr = NULL; before = ewPtr->body.ew.create; /* * Find everything up to the next % character and append it to the * result string. */ string = before; while (*string != 0) { if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) { if (dsPtr == NULL) { Tcl_DStringInit(&buf); dsPtr = &buf; } if (string != before) { Tcl_DStringAppend(dsPtr, before, (int) (string-before)); before = string; } if (string[1] == '%') { Tcl_DStringAppend(dsPtr, "%", 1); } else { /* * Substitute string as proper Tcl list element. */ int spaceNeeded, cvtFlags, length; const char *str = Tk_PathName(textPtr->tkwin); spaceNeeded = Tcl_ScanElement(str, &cvtFlags); length = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, length + spaceNeeded); spaceNeeded = Tcl_ConvertElement(str, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES); Tcl_DStringSetLength(dsPtr, length + spaceNeeded); } before += 2; string++; } string++; } /* * The window doesn't currently exist. Create it by evaluating the * creation script. The script must return the window's path name: * look up that name to get back to the window token. Then register * ourselves as the geometry manager for the window. */ if (dsPtr != NULL) { Tcl_DStringAppend(dsPtr, before, (int) (string-before)); code = Tcl_GlobalEval(textPtr->interp, Tcl_DStringValue(dsPtr)); Tcl_DStringFree(dsPtr); } else { code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create); } if (code != TCL_OK) { createError: Tcl_BackgroundException(textPtr->interp, code); goto gotWindow; } Tcl_DStringInit(&name); Tcl_DStringAppend(&name, Tcl_GetStringResult(textPtr->interp), -1); Tcl_ResetResult(textPtr->interp); ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp, Tcl_DStringValue(&name), textPtr->tkwin); Tcl_DStringFree(&name); if (ewPtr->body.ew.tkwin == NULL) { goto createError; } for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) { break; } if (Tk_TopWinHierarchy(ancestor)) { badMaster: Tcl_AppendResult(textPtr->interp, "can't embed ", Tk_PathName(ewPtr->body.ew.tkwin), " relative to ", Tk_PathName(textPtr->tkwin), NULL); Tcl_BackgroundError(textPtr->interp); ewPtr->body.ew.tkwin = NULL; goto gotWindow; } } if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin) || (textPtr->tkwin == ewPtr->body.ew.tkwin)) { goto badMaster; } if (client == NULL) { /* * We just used a '-create' script to make a new window, which we * now need to add to our client list. */ client = (TkTextEmbWindowClient *) ckalloc(sizeof(TkTextEmbWindowClient)); client->next = ewPtr->body.ew.clients; client->textPtr = textPtr; client->tkwin = NULL; client->chunkCount = 0; client->displayed = 0; client->parent = ewPtr; ewPtr->body.ew.clients = client; } client->tkwin = ewPtr->body.ew.tkwin; Tk_ManageGeometry(client->tkwin, &textGeomType, client); Tk_CreateEventHandler(client->tkwin, StructureNotifyMask, EmbWinStructureProc, client); /* * Special trick! Must enter into the hash table *after* calling * Tk_ManageGeometry: if the window was already managed elsewhere in * this text, the Tk_ManageGeometry call will cause the entry to be * removed, which could potentially lose the new entry. */ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable, Tk_PathName(client->tkwin), &isNew); Tcl_SetHashValue(hPtr, ewPtr); } /* * See if there's room for this window on this line. */ gotWindow: if (ewPtr->body.ew.tkwin == NULL) { width = 0; height = 0; } else { width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX; height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY; } if ((width > (maxX - chunkPtr->x)) && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) { return 0; } /* * Fill in the chunk structure. */ chunkPtr->displayProc = TkTextEmbWinDisplayProc; chunkPtr->undisplayProc = EmbWinUndisplayProc; chunkPtr->measureProc = NULL; chunkPtr->bboxProc = EmbWinBboxProc; chunkPtr->numBytes = 1; if (ewPtr->body.ew.align == ALIGN_BASELINE) { chunkPtr->minAscent = height - ewPtr->body.ew.padY; chunkPtr->minDescent = ewPtr->body.ew.padY; chunkPtr->minHeight = 0; } else { chunkPtr->minAscent = 0; chunkPtr->minDescent = 0; chunkPtr->minHeight = height; } chunkPtr->width = width; chunkPtr->breakIndex = -1; chunkPtr->breakIndex = 1; chunkPtr->clientData = ewPtr; if (client != NULL) { client->chunkCount += 1; } return 1; }
void TkTextEmbWinDisplayProc( TkText *textPtr, /* Information about text widget. */ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */ int x, /* X-position in dst at which to draw this * chunk (differs from the x-position in the * chunk because of scrolling). */ int y, /* Top of rectangular bounding box for line: * tells where to draw this chunk in dst * (x-position is in the chunk itself). */ int lineHeight, /* Total height of line. */ int baseline, /* Offset of baseline from y. */ Display *display, /* Display to use for drawing (unused). */ Drawable dst, /* Pixmap or window in which to draw * (unused). */ int screenY) /* Y-coordinate in text window that * corresponds to y. */ { int lineX, windowX, windowY, width, height; Tk_Window tkwin; TkTextSegment *ewPtr = chunkPtr->clientData; TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr); if (client == NULL) { return; } tkwin = client->tkwin; if (tkwin == NULL) { return; } if ((x + chunkPtr->width) <= 0) { /* * The window is off-screen; just unmap it. */ if (textPtr->tkwin != Tk_Parent(tkwin)) { Tk_UnmaintainGeometry(tkwin, textPtr->tkwin); } else { Tk_UnmapWindow(tkwin); } return; } /* * Compute the window's location and size in the text widget, taking into * account the align and stretch values for the window. */ EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline, &lineX, &windowY, &width, &height); windowX = lineX - chunkPtr->x + x; if (textPtr->tkwin == Tk_Parent(tkwin)) { if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin)) || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin)) || (height != Tk_Height(tkwin))) { Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height); } Tk_MapWindow(tkwin); } else { Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY, width, height); } /* * Mark the window as displayed so that it won't get unmapped. */ client->displayed = 1; }
static void ComputeWindowBbox( Tk_Canvas canvas, /* Canvas that contains item. */ WindowItem *winItemPtr) /* Item whose bbox is to be recomputed. */ { int width, height, x, y; Tk_State state = winItemPtr->header.state; x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5)); y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5)); if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) { /* * There is no window for this item yet. Just give it a 1x1 bounding * box. Don't give it a 0x0 bounding box; there are strange cases * where this bounding box might be used as the dimensions of the * window, and 0x0 causes problems under X. */ winItemPtr->header.x1 = x; winItemPtr->header.x2 = winItemPtr->header.x1 + 1; winItemPtr->header.y1 = y; winItemPtr->header.y2 = winItemPtr->header.y1 + 1; return; } /* * Compute dimensions of window. */ width = winItemPtr->width; if (width <= 0) { width = Tk_ReqWidth(winItemPtr->tkwin); if (width <= 0) { width = 1; } } height = winItemPtr->height; if (height <= 0) { height = Tk_ReqHeight(winItemPtr->tkwin); if (height <= 0) { height = 1; } } /* * Compute location of window, using anchor information. */ switch (winItemPtr->anchor) { case TK_ANCHOR_N: x -= width/2; break; case TK_ANCHOR_NE: x -= width; break; case TK_ANCHOR_E: x -= width; y -= height/2; break; case TK_ANCHOR_SE: x -= width; y -= height; break; case TK_ANCHOR_S: x -= width/2; y -= height; break; case TK_ANCHOR_SW: y -= height; break; case TK_ANCHOR_W: y -= height/2; break; case TK_ANCHOR_NW: break; case TK_ANCHOR_CENTER: x -= width/2; y -= height/2; break; } /* * Store the information in the item header. */ winItemPtr->header.x1 = x; winItemPtr->header.y1 = y; winItemPtr->header.x2 = x + width; winItemPtr->header.y2 = y + height; }