📄 tklistbox.c
字号:
* * Results: * A standard Tcl result. If all went well, then *indexPtr is * filled in with the index (into listPtr) corresponding to * string. Otherwise an error message is left in interp->result. * * Side effects: * None. * *-------------------------------------------------------------- */static intGetListboxIndex(interp, listPtr, string, endIsSize, indexPtr) Tcl_Interp *interp; /* For error messages. */ Listbox *listPtr; /* Listbox for which the index is being * specified. */ char *string; /* Specifies an element in the listbox. */ int endIsSize; /* If 1, "end" refers to the number of * entries in the listbox. If 0, "end" * refers to 1 less than the number of * entries. */ int *indexPtr; /* Where to store converted index. */{ int c; size_t length; length = strlen(string); c = string[0]; if ((c == 'a') && (strncmp(string, "active", length) == 0) && (length >= 2)) { *indexPtr = listPtr->active; } else if ((c == 'a') && (strncmp(string, "anchor", length) == 0) && (length >= 2)) { *indexPtr = listPtr->selectAnchor; } else if ((c == 'e') && (strncmp(string, "end", length) == 0)) { if (endIsSize) { *indexPtr = listPtr->numElements; } else { *indexPtr = listPtr->numElements - 1; } } else if (c == '@') { int y; char *p, *end; p = string+1; strtol(p, &end, 0); if ((end == p) || (*end != ',')) { goto badIndex; } p = end+1; y = strtol(p, &end, 0); if ((end == p) || (*end != 0)) { goto badIndex; } *indexPtr = NearestListboxElement(listPtr, y); } else { if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) { Tcl_ResetResult(interp); goto badIndex; } } return TCL_OK; badIndex: Tcl_AppendResult(interp, "bad listbox index \"", string, "\": must be active, anchor, end, @x,y, or a number", (char *) NULL); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * ChangeListboxView -- * * Change the view on a listbox widget so that a given element * is displayed at the top. * * Results: * None. * * Side effects: * What's displayed on the screen is changed. If there is a * scrollbar associated with this widget, then the scrollbar * is instructed to change its display too. * *---------------------------------------------------------------------- */static voidChangeListboxView(listPtr, index) register Listbox *listPtr; /* Information about widget. */ int index; /* Index of element in listPtr * that should now appear at the * top of the listbox. */{ if (index >= (listPtr->numElements - listPtr->fullLines)) { index = listPtr->numElements - listPtr->fullLines; } if (index < 0) { index = 0; } if (listPtr->topIndex != index) { listPtr->topIndex = index; if (!(listPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayListbox, (ClientData) listPtr); listPtr->flags |= REDRAW_PENDING; } listPtr->flags |= UPDATE_V_SCROLLBAR; }}/* *---------------------------------------------------------------------- * * ChangListboxOffset -- * * Change the horizontal offset for a listbox. * * Results: * None. * * Side effects: * The listbox may be redrawn to reflect its new horizontal * offset. * *---------------------------------------------------------------------- */static voidChangeListboxOffset(listPtr, offset) register Listbox *listPtr; /* Information about widget. */ int offset; /* Desired new "xOffset" for * listbox. */{ int maxOffset; /* * Make sure that the new offset is within the allowable range, and * round it off to an even multiple of xScrollUnit. */ maxOffset = listPtr->maxWidth - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset - 2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1; if (offset > maxOffset) { offset = maxOffset; } if (offset < 0) { offset = 0; } offset -= offset % listPtr->xScrollUnit; if (offset != listPtr->xOffset) { listPtr->xOffset = offset; listPtr->flags |= UPDATE_H_SCROLLBAR; ListboxRedrawRange(listPtr, 0, listPtr->numElements); }}/* *---------------------------------------------------------------------- * * ListboxScanTo -- * * Given a point (presumably of the curent mouse location) * drag the view in the window to implement the scan operation. * * Results: * None. * * Side effects: * The view in the window may change. * *---------------------------------------------------------------------- */static voidListboxScanTo(listPtr, x, y) register Listbox *listPtr; /* Information about widget. */ int x; /* X-coordinate to use for scan * operation. */ int y; /* Y-coordinate to use for scan * operation. */{ int newTopIndex, newOffset, maxIndex, maxOffset; maxIndex = listPtr->numElements - listPtr->fullLines; maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1) - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset - 2*listPtr->selBorderWidth - listPtr->xScrollUnit); /* * Compute new top line for screen by amplifying the difference * between the current position and the place where the scan * started (the "mark" position). If we run off the top or bottom * of the list, then reset the mark point so that the current * position continues to correspond to the edge of the window. * This means that the picture will start dragging as soon as the * mouse reverses direction (without this reset, might have to slide * mouse a long ways back before the picture starts moving again). */ newTopIndex = listPtr->scanMarkYIndex - (10*(y - listPtr->scanMarkY))/listPtr->lineHeight; if (newTopIndex > maxIndex) { newTopIndex = listPtr->scanMarkYIndex = maxIndex; listPtr->scanMarkY = y; } else if (newTopIndex < 0) { newTopIndex = listPtr->scanMarkYIndex = 0; listPtr->scanMarkY = y; } ChangeListboxView(listPtr, newTopIndex); /* * Compute new left edge for display in a similar fashion by amplifying * the difference between the current position and the place where the * scan started. */ newOffset = listPtr->scanMarkXOffset - (10*(x - listPtr->scanMarkX)); if (newOffset > maxOffset) { newOffset = listPtr->scanMarkXOffset = maxOffset; listPtr->scanMarkX = x; } else if (newOffset < 0) { newOffset = listPtr->scanMarkXOffset = 0; listPtr->scanMarkX = x; } ChangeListboxOffset(listPtr, newOffset);}/* *---------------------------------------------------------------------- * * NearestListboxElement -- * * Given a y-coordinate inside a listbox, compute the index of * the element under that y-coordinate (or closest to that * y-coordinate). * * Results: * The return value is an index of an element of listPtr. If * listPtr has no elements, then 0 is always returned. * * Side effects: * None. * *---------------------------------------------------------------------- */static intNearestListboxElement(listPtr, y) register Listbox *listPtr; /* Information about widget. */ int y; /* Y-coordinate in listPtr's window. */{ int index; index = (y - listPtr->inset)/listPtr->lineHeight; if (index >= (listPtr->fullLines + listPtr->partialLine)) { index = listPtr->fullLines + listPtr->partialLine - 1; } if (index < 0) { index = 0; } index += listPtr->topIndex; if (index >= listPtr->numElements) { index = listPtr->numElements-1; } return index;}/* *---------------------------------------------------------------------- * * ListboxSelect -- * * Select or deselect one or more elements in a listbox.. * * Results: * None. * * Side effects: * All of the elements in the range between first and last are * marked as either selected or deselected, depending on the * "select" argument. Any items whose state changes are redisplayed. * The selection is claimed from X when the number of selected * elements changes from zero to non-zero. * *---------------------------------------------------------------------- */static voidListboxSelect(listPtr, first, last, select) register Listbox *listPtr; /* Information about widget. */ int first; /* Index of first element to * select or deselect. */ int last; /* Index of last element to * select or deselect. */ int select; /* 1 means select items, 0 means * deselect them. */{ int i, firstRedisplay, increment, oldCount; Element *elPtr; if (last < first) { i = first; first = last; last = i; } if ((last < 0) || (first >= listPtr->numElements)) { return; } if (first < 0) { first = 0; } if (last >= listPtr->numElements) { last = listPtr->numElements - 1; } oldCount = listPtr->numSelected; firstRedisplay = -1; increment = select ? 1 : -1; for (i = 0, elPtr = listPtr->firstPtr; i < first; i++, elPtr = elPtr->nextPtr) { /* Empty loop body. */ } for ( ; i <= last; i++, elPtr = elPtr->nextPtr) { if (elPtr->selected == select) { continue; } listPtr->numSelected += increment; elPtr->selected = select; if (firstRedisplay < 0) { firstRedisplay = i; } } if (firstRedisplay >= 0) { ListboxRedrawRange(listPtr, first, last); } if ((oldCount == 0) && (listPtr->numSelected > 0) && (listPtr->exportSelection)) { Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection, (ClientData) listPtr); }}/* *---------------------------------------------------------------------- * * ListboxFetchSelection -- * * This procedure is called back by Tk when the selection is * requested by someone. It returns part or all of the selection * in a buffer provided by the caller. * * Results: * The return value is the number of non-NULL bytes stored * at buffer. Buffer is filled (or partially filled) with a * NULL-terminated string containing part or all of the selection, * as given by offset and maxBytes. The selection is returned * as a Tcl list with one list element for each element in the * listbox. * * Side effects: * None. * *---------------------------------------------------------------------- */static intListboxFetchSelection(clientData, offset, buffer, maxBytes) ClientData clientData; /* Information about listbox widget. */ int offset; /* Offset within selection of first * byte to be returned. */ char *buffer; /* Location in which to place * selection. */ int maxBytes; /* Maximum number of bytes to place * at buffer, not including terminating * NULL character. */{ register Listbox *listPtr = (Listbox *) clientData; register Element *elPtr; Tcl_DString selection; int length, count, needNewline; if (!listPtr->exportSelection) { return -1; } /* * Use a dynamic string to accumulate the contents of the selection. */ needNewline = 0; Tcl_DStringInit(&selection); for (elPtr = listPtr->firstPtr; elPtr != NULL; elPtr = elPtr->nextPtr) { if (elPtr->selected) { if (needNewline) { Tcl_DStringAppend(&selection, "\n", 1); } Tcl_DStringAppend(&selection, elPtr->text, elPtr->textLength); needNewline = 1; } } length = Tcl_DStringLength(&selection); if (length == 0) { return -1; } /* * Copy the requested portion of the selection to the buffer. */ count = length - offset; if (count <= 0) { count = 0; } else { if (count > maxBytes) { count = maxBytes; } memcpy((VOID *) buffer, (VOID *) (Tcl_DStringValue(&selection) + offset), (size_t) count); } buffer[count] = '\0'; Tcl_DStringFree(&selection); return count
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -