📄 tkmessage.c
字号:
if (msgPtr->textVarName != NULL) { Tcl_UntraceVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, (ClientData) msgPtr); } if (Tk_ConfigureWidget(interp, msgPtr->tkwin, configSpecs, argc, argv, (char *) msgPtr, flags) != TCL_OK) { return TCL_ERROR; } /* * If the message is to display the value of a variable, then set up * a trace on the variable's value, create the variable if it doesn't * exist, and fetch its current value. */ if (msgPtr->textVarName != NULL) { char *value; value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY); if (value == NULL) { Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string, TCL_GLOBAL_ONLY); } else { if (msgPtr->string != NULL) { ckfree(msgPtr->string); } msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value); } Tcl_TraceVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, (ClientData) msgPtr); } /* * A few other options need special processing, such as setting * the background from a 3-D border or handling special defaults * that couldn't be specified to Tk_ConfigureWidget. */ msgPtr->numChars = strlen(msgPtr->string); Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border); if (msgPtr->highlightWidth < 0) { msgPtr->highlightWidth = 0; } MessageWorldChanged((ClientData) msgPtr); return TCL_OK;}/* *--------------------------------------------------------------------------- * * MessageWorldChanged -- * * This procedure is called when the world has changed in some * way and the widget needs to recompute all its graphics contexts * and determine its new geometry. * * Results: * None. * * Side effects: * Message will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static voidMessageWorldChanged(instanceData) ClientData instanceData; /* Information about widget. */{ XGCValues gcValues; GC gc; Tk_FontMetrics fm; Message *msgPtr; msgPtr = (Message *) instanceData; gcValues.font = Tk_FontId(msgPtr->tkfont); gcValues.foreground = msgPtr->fgColorPtr->pixel; gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues); if (msgPtr->textGC != None) { Tk_FreeGC(msgPtr->display, msgPtr->textGC); } msgPtr->textGC = gc; Tk_GetFontMetrics(msgPtr->tkfont, &fm); if (msgPtr->padX < 0) { msgPtr->padX = fm.ascent / 2; } if (msgPtr->padY == -1) { msgPtr->padY = fm.ascent / 4; } /* * Recompute the desired geometry for the window, and arrange for * the window to be redisplayed. */ ComputeMessageGeometry(msgPtr); if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin) && !(msgPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr); msgPtr->flags |= REDRAW_PENDING; }}/* *-------------------------------------------------------------- * * ComputeMessageGeometry -- * * Compute the desired geometry for a message window, * taking into account the desired aspect ratio for the * window. * * Results: * None. * * Side effects: * Tk_GeometryRequest is called to inform the geometry * manager of the desired geometry for this window. * *-------------------------------------------------------------- */static voidComputeMessageGeometry(msgPtr) register Message *msgPtr; /* Information about window. */{ int width, inc, height; int thisWidth, thisHeight, maxWidth; int aspect, lowerBound, upperBound, inset; Tk_FreeTextLayout(msgPtr->textLayout); inset = msgPtr->borderWidth + msgPtr->highlightWidth; /* * Compute acceptable bounds for the final aspect ratio. */ aspect = msgPtr->aspect/10; if (aspect < 5) { aspect = 5; } lowerBound = msgPtr->aspect - aspect; upperBound = msgPtr->aspect + aspect; /* * Do the computation in multiple passes: start off with * a very wide window, and compute its height. Then change * the width and try again. Reduce the size of the change * and iterate until dimensions are found that approximate * the desired aspect ratio. Or, if the user gave an explicit * width then just use that. */ if (msgPtr->width > 0) { width = msgPtr->width; inc = 0; } else { width = WidthOfScreen(Tk_Screen(msgPtr->tkwin))/2; inc = width/2; } for ( ; ; inc /= 2) { msgPtr->textLayout = Tk_ComputeTextLayout(msgPtr->tkfont, msgPtr->string, msgPtr->numChars, width, msgPtr->justify, 0, &thisWidth, &thisHeight); maxWidth = thisWidth + 2 * (inset + msgPtr->padX); height = thisHeight + 2 * (inset + msgPtr->padY); if (inc <= 2) { break; } aspect = (100 * maxWidth) / height; if (aspect < lowerBound) { width += inc; } else if (aspect > upperBound) { width -= inc; } else { break; } Tk_FreeTextLayout(msgPtr->textLayout); } msgPtr->msgWidth = thisWidth; msgPtr->msgHeight = thisHeight; Tk_GeometryRequest(msgPtr->tkwin, maxWidth, height); Tk_SetInternalBorder(msgPtr->tkwin, inset);}/* *-------------------------------------------------------------- * * DisplayMessage -- * * This procedure redraws the contents of a message window. * * Results: * None. * * Side effects: * Information appears on the screen. * *-------------------------------------------------------------- */static voidDisplayMessage(clientData) ClientData clientData; /* Information about window. */{ register Message *msgPtr = (Message *) clientData; register Tk_Window tkwin = msgPtr->tkwin; int x, y; msgPtr->flags &= ~REDRAW_PENDING; if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); /* * Compute starting y-location for message based on message size * and anchor option. */ TkComputeAnchor(msgPtr->anchor, tkwin, msgPtr->padX, msgPtr->padY, msgPtr->msgWidth, msgPtr->msgHeight, &x, &y); Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC, msgPtr->textLayout, x, y, 0, -1); if (msgPtr->relief != TK_RELIEF_FLAT) { Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border, msgPtr->highlightWidth, msgPtr->highlightWidth, Tk_Width(tkwin) - 2*msgPtr->highlightWidth, Tk_Height(tkwin) - 2*msgPtr->highlightWidth, msgPtr->borderWidth, msgPtr->relief); } if (msgPtr->highlightWidth != 0) { GC gc; if (msgPtr->flags & GOT_FOCUS) { gc = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin)); } else { gc = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin)); } Tk_DrawFocusHighlight(tkwin, gc, msgPtr->highlightWidth, Tk_WindowId(tkwin)); }}/* *-------------------------------------------------------------- * * MessageEventProc -- * * This procedure is invoked by the Tk dispatcher for various * events on messages. * * Results: * None. * * Side effects: * When the window gets deleted, internal structures get * cleaned up. When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */static voidMessageEventProc(clientData, eventPtr) ClientData clientData; /* Information about window. */ XEvent *eventPtr; /* Information about event. */{ Message *msgPtr = (Message *) clientData; if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) || (eventPtr->type == ConfigureNotify)) { goto redraw; } else if (eventPtr->type == DestroyNotify) { if (msgPtr->tkwin != NULL) { msgPtr->tkwin = NULL; Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd); } if (msgPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayMessage, (ClientData) msgPtr); } Tcl_EventuallyFree((ClientData) msgPtr, DestroyMessage); } else if (eventPtr->type == FocusIn) { if (eventPtr->xfocus.detail != NotifyInferior) { msgPtr->flags |= GOT_FOCUS; if (msgPtr->highlightWidth > 0) { goto redraw; } } } else if (eventPtr->type == FocusOut) { if (eventPtr->xfocus.detail != NotifyInferior) { msgPtr->flags &= ~GOT_FOCUS; if (msgPtr->highlightWidth > 0) { goto redraw; } } } return; redraw: if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr); msgPtr->flags |= REDRAW_PENDING; }}/* *---------------------------------------------------------------------- * * MessageCmdDeletedProc -- * * This procedure is invoked when a widget command is deleted. If * the widget isn't already in the process of being destroyed, * this command destroys it. * * Results: * None. * * Side effects: * The widget is destroyed. * *---------------------------------------------------------------------- */static voidMessageCmdDeletedProc(clientData) ClientData clientData; /* Pointer to widget record for widget. */{ Message *msgPtr = (Message *) clientData; Tk_Window tkwin = msgPtr->tkwin; /* * This procedure could be invoked either because the window was * destroyed and the command was then deleted (in which case tkwin * is NULL) or because the command was deleted, and then this procedure * destroys the widget. */ if (tkwin != NULL) { msgPtr->tkwin = NULL; Tk_DestroyWindow(tkwin); }}/* *-------------------------------------------------------------- * * MessageTextVarProc -- * * This procedure is invoked when someone changes the variable * whose contents are to be displayed in a message. * * Results: * NULL is always returned. * * Side effects: * The text displayed in the message will change to match the * variable. * *-------------------------------------------------------------- */ /* ARGSUSED */static char *MessageTextVarProc(clientData, interp, name1, name2, flags) ClientData clientData; /* Information about message. */ Tcl_Interp *interp; /* Interpreter containing variable. */ char *name1; /* Name of variable. */ char *name2; /* Second part of variable name. */ int flags; /* Information about what happened. */{ register Message *msgPtr = (Message *) clientData; char *value; /* * If the variable is unset, then immediately recreate it unless * the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { Tcl_SetVar(interp, msgPtr->textVarName, msgPtr->string, TCL_GLOBAL_ONLY); Tcl_TraceVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, clientData); } return (char *) NULL; } value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY); if (value == NULL) { value = ""; } if (msgPtr->string != NULL) { ckfree(msgPtr->string); } msgPtr->numChars = strlen(value); msgPtr->string = (char *) ckalloc((unsigned) (msgPtr->numChars + 1)); strcpy(msgPtr->string, value); ComputeMessageGeometry(msgPtr); if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin) && !(msgPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr); msgPtr->flags |= REDRAW_PENDING; } return (char *) NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -