int TkTextWindowCmd( register TkText *textPtr, /* Information about text widget. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that * objv[1] is "window". */ { int optionIndex; static const char *const windOptionStrings[] = { "cget", "configure", "create", "names", NULL }; enum windOptions { WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES }; register TkTextSegment *ewPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], windOptionStrings, "window option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum windOptions) optionIndex) { case WIND_CGET: { TkTextIndex index; TkTextSegment *ewPtr; Tcl_Obj *objPtr; TkTextEmbWindowClient *client; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "index option"); return TCL_ERROR; } if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } ewPtr = TkTextIndexToSeg(&index, NULL); if (ewPtr->typePtr != &tkTextEmbWindowType) { Tcl_AppendResult(interp, "no embedded window at index \"", Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } /* * Copy over client specific value before querying. */ client = EmbWinGetClient(textPtr, ewPtr); if (client != NULL) { ewPtr->body.ew.tkwin = client->tkwin; } else { ewPtr->body.ew.tkwin = NULL; } objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } case WIND_CONFIGURE: { TkTextIndex index; TkTextSegment *ewPtr; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?"); return TCL_ERROR; } if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } ewPtr = TkTextIndexToSeg(&index, NULL); if (ewPtr->typePtr != &tkTextEmbWindowType) { Tcl_AppendResult(interp, "no embedded window at index \"", Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } if (objc <= 5) { TkTextEmbWindowClient *client; Tcl_Obj *objPtr; /* * Copy over client specific value before querying. */ client = EmbWinGetClient(textPtr, ewPtr); if (client != NULL) { ewPtr->body.ew.tkwin = client->tkwin; } else { ewPtr->body.ew.tkwin = NULL; } objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL, textPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } else { TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); /* * It's probably not true that all window configuration can change * the line height, so we could be more efficient here and only * call this when necessary. */ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4); } } case WIND_CREATE: { TkTextIndex index; int lineIndex; TkTextEmbWindowClient *client; int res; /* * Add a new window. Find where to put the new window, and mark that * position for redisplay. */ if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?"); return TCL_ERROR; } if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } /* * Don't allow insertions on the last (dummy) line of the text. */ lineIndex = TkBTreeLinesTo(textPtr, index.linePtr); if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr)) { lineIndex--; TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineIndex, 1000000, &index); } /* * Create the new window segment and initialize it. */ ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE); ewPtr->typePtr = &tkTextEmbWindowType; ewPtr->size = 1; ewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr; ewPtr->body.ew.linePtr = NULL; ewPtr->body.ew.tkwin = NULL; ewPtr->body.ew.create = NULL; ewPtr->body.ew.align = ALIGN_CENTER; ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0; ewPtr->body.ew.stretch = 0; ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs); client = (TkTextEmbWindowClient *) ckalloc(sizeof(TkTextEmbWindowClient)); client->next = NULL; client->textPtr = textPtr; client->tkwin = NULL; client->chunkCount = 0; client->displayed = 0; client->parent = ewPtr; ewPtr->body.ew.clients = client; /* * Link the segment into the text widget, then configure it (delete it * again if the configuration fails). */ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); TkBTreeLinkSegment(ewPtr, &index); res = EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4); client->tkwin = ewPtr->body.ew.tkwin; if (res != TCL_OK) { TkTextIndex index2; TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES); TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index, &index2); return TCL_ERROR; } TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); break; } case WIND_NAMES: { Tcl_HashSearch search; Tcl_HashEntry *hPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_AppendElement(interp, Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr)); } break; } } return TCL_OK; }
int tk_text_buffer(Tcl_DString * buf, int buf_size, void *idx1, void *idx2) { int i, size; TkTextIndex *lex_index1 = (TkTextIndex *) idx1; TkTextIndex *lex_end_index = (TkTextIndex *) idx2; /* Get a handle to tkTextCharType. */ #ifndef WIN32 static Tk_SegType *tk_text_tp = &tkTextCharType; #else /* Under Win32, we may need to load the DLL. */ static int first = 1; static Tk_SegType *tk_text_tp; if(first) { HINSTANCE tkdll; char dllname[MAX_PATH]; first = 0; sprintf(dllname, "rhtk%d%d%s.dll", TK_MAJOR_VERSION, TK_MINOR_VERSION, TK_DBGX); LOGGER((LOGFP, "GetModuleHandle: <%s>\n", dllname)); tkdll = LoadLibrary(dllname); if(!tkdll) { panic("could not load dll \"%s\"\n", dllname); } tk_text_tp = (Tk_SegType *) GetProcAddress(tkdll, "tkTextCharType"); FreeLibrary(tkdll); } #endif /* WIN32 */ /* What does this do? */ if(eos_read) { return 0; } /* Extract characters from the Tk text widget. */ for (size = 0, i = 0; (buf_size == 0 || i < buf_size); i++) { int offset, last; TkTextSegment *segPtr; segPtr = TkTextIndexToSeg(lex_index1, &offset); last = segPtr->size; /* Are we on the last line of the Tk text buffer? */ if(lex_index1->linePtr == lex_end_index->linePtr) { int last2; /* Is this the end of the Tk text buffer? */ if(lex_end_index->CHARINDEX == lex_index1->CHARINDEX) { break; } last2 = lex_end_index->CHARINDEX - lex_index1->CHARINDEX + offset; if(last2 < last) { last = last2; } } /* Is the segement element a piece of text? */ if(segPtr->typePtr == tk_text_tp) { int size2 = last - offset; Tcl_DStringAppend(buf, segPtr->body.chars + offset, size2); size += size2; TkTextIndexForwBytes(lex_index1, size2, lex_index1); } else { /* No. Just skip over it. */ TkTextIndexForwBytes(lex_index1, last - offset, lex_index1); } } return size; }