📄 text.c
字号:
splitting windows on Linux 2.0 systems (same Motif, why the change in behavior?), causes one or two resize calls with < 1 line of height. Fixing it here is 100x easier than re-designing textDisp.c */ if (w->text.columns < 1) { w->text.columns = 1; w->core.width = width = fs->max_bounds.width + marginWidth*2 + lineNumAreaWidth; } if (w->text.rows < 1) { w->text.rows = 1; w->core.height = height = fs->ascent + fs->descent + marginHeight*2; } /* Resize the text display that the widget uses to render text */ TextDResize(w->text.textD, width - marginWidth*2 - lineNumAreaWidth, height - marginHeight*2); /* if the window became shorter or narrower, there may be text left in the bottom or right margin area, which must be cleaned up */ if (XtIsRealized((Widget)w)) { XClearArea(XtDisplay(w), XtWindow(w), 0, height-marginHeight, width, marginHeight, False); XClearArea(XtDisplay(w), XtWindow(w),width-marginWidth, 0, marginWidth, height, False); }}/*** Widget redisplay method*/static void redisplay(TextWidget w, XEvent *event, Region region){ XExposeEvent *e = &event->xexpose; TextDRedisplayRect(w->text.textD, e->x, e->y, e->width, e->height);}static Bool findGraphicsExposeOrNoExposeEvent(Display *theDisplay, XEvent *event, XPointer arg){ if ((theDisplay == event->xany.display) && (event->type == GraphicsExpose || event->type == NoExpose) && ((Widget)arg == XtWindowToWidget(event->xany.display, event->xany.window))) { return(True); } else { return(False); }}static void adjustRectForGraphicsExposeOrNoExposeEvent(TextWidget w, XEvent *event, Boolean *first, int *left, int *top, int *width, int *height){ Boolean removeQueueEntry = False; if (event->type == GraphicsExpose) { XGraphicsExposeEvent *e = &event->xgraphicsexpose; int x = e->x, y = e->y; TextDImposeGraphicsExposeTranslation(w->text.textD, &x, &y); if (*first) { *left = x; *top = y; *width = e->width; *height = e->height; *first = False; } else { int prev_left = *left; int prev_top = *top; *left = min(*left, x); *top = min(*top, y); *width = max(prev_left + *width, x + e->width) - *left; *height = max(prev_top + *height, y + e->height) - *top; } if (e->count == 0) { removeQueueEntry = True; } } else if (event->type == NoExpose) { removeQueueEntry = True; } if (removeQueueEntry) { TextDPopGraphicExposeQueueEntry(w->text.textD); }}static void redisplayGE(TextWidget w, XtPointer client_data, XEvent *event, Boolean *continue_to_dispatch_return){ if (event->type == GraphicsExpose || event->type == NoExpose) { HandleAllPendingGraphicsExposeNoExposeEvents(w, event); }}void HandleAllPendingGraphicsExposeNoExposeEvents(TextWidget w, XEvent *event){ XEvent foundEvent; int left; int top; int width; int height; Boolean invalidRect = True; if (event) { adjustRectForGraphicsExposeOrNoExposeEvent(w, event, &invalidRect, &left, &top, &width, &height); } while (XCheckIfEvent(XtDisplay(w), &foundEvent, findGraphicsExposeOrNoExposeEvent, (XPointer)w)) { adjustRectForGraphicsExposeOrNoExposeEvent(w, &foundEvent, &invalidRect, &left, &top, &width, &height); } if (!invalidRect) { TextDRedisplayRect(w->text.textD, left, top, width, height); }}/*** Widget setValues method*/static Boolean setValues(TextWidget current, TextWidget request, TextWidget new){ Boolean redraw = False, reconfigure = False; if (new->text.overstrike != current->text.overstrike) { if (current->text.textD->cursorStyle == BLOCK_CURSOR) TextDSetCursorStyle(current->text.textD, current->text.heavyCursor ? HEAVY_CURSOR : NORMAL_CURSOR); else if (current->text.textD->cursorStyle == NORMAL_CURSOR || current->text.textD->cursorStyle == HEAVY_CURSOR) TextDSetCursorStyle(current->text.textD, BLOCK_CURSOR); } if (new->text.fontStruct != current->text.fontStruct) { if (new->text.lineNumCols != 0) reconfigure = True; TextDSetFont(current->text.textD, new->text.fontStruct); } if (new->text.wrapMargin != current->text.wrapMargin || new->text.continuousWrap != current->text.continuousWrap) TextDSetWrapMode(current->text.textD, new->text.continuousWrap, new->text.wrapMargin); /* When delimiters are changed, copy the memory, so that the caller doesn't have to manage it, and add mandatory delimiters blank, tab, and newline to the list */ if (new->text.delimiters != current->text.delimiters) { char *delimiters = XtMalloc(strlen(new->text.delimiters) + 4); XtFree(current->text.delimiters); sprintf(delimiters, "%s%s", " \t\n", new->text.delimiters); new->text.delimiters = delimiters; } /* Setting the lineNumCols resource tells the text widget to hide or show, or change the number of columns of the line number display, which requires re-organizing the x coordinates of both the line number display and the main text display */ if (new->text.lineNumCols != current->text.lineNumCols || reconfigure) { int marginWidth = new->text.marginWidth; int charWidth = new->text.fontStruct->max_bounds.width; int lineNumCols = new->text.lineNumCols; if (lineNumCols == 0) { TextDSetLineNumberArea(new->text.textD, 0, 0, marginWidth); new->text.columns = (new->core.width - marginWidth*2) / charWidth; } else { TextDSetLineNumberArea(new->text.textD, marginWidth, charWidth * lineNumCols, 2*marginWidth + charWidth * lineNumCols); new->text.columns = (new->core.width - marginWidth*3 - charWidth * lineNumCols) / charWidth; } } if (new->text.backlightCharTypes != current->text.backlightCharTypes) { TextDSetupBGClasses((Widget)new, new->text.backlightCharTypes, &new->text.textD->bgClassPixel, &new->text.textD->bgClass, new->text.textD->bgPixel); redraw = True; } return redraw;} /*** Widget realize method*/static void realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attributes){ /* Set bit gravity window attribute. This saves a full blank and redraw on window resizing */ *valueMask |= CWBitGravity; attributes->bit_gravity = NorthWestGravity; /* Continue with realize method from superclass */ (xmPrimitiveClassRec.core_class.realize)(w, valueMask, attributes);}/*** Widget query geometry method ... unless asked to negotiate a different size simply return current size.*/static XtGeometryResult queryGeometry(Widget w, XtWidgetGeometry *proposed, XtWidgetGeometry *answer){ TextWidget tw = (TextWidget)w; int curHeight = tw->core.height; int curWidth = tw->core.width; XFontStruct *fs = tw->text.textD->fontStruct; int fontWidth = fs->max_bounds.width; int fontHeight = fs->ascent + fs->descent; int marginHeight = tw->text.marginHeight; int propWidth = (proposed->request_mode & CWWidth) ? proposed->width : 0; int propHeight = (proposed->request_mode & CWHeight) ? proposed->height : 0; answer->request_mode = CWHeight | CWWidth; if(proposed->request_mode & CWWidth) /* Accept a width no smaller than 10 chars */ answer->width = max(fontWidth * 10, proposed->width); else answer->width = curWidth; if(proposed->request_mode & CWHeight) /* Accept a height no smaller than an exact multiple of the line height and at least one line high */ answer->height = max(1, ((propHeight - 2*marginHeight) / fontHeight)) * fontHeight + 2*marginHeight; else answer->height = curHeight; /*printf("propWidth %d, propHeight %d, ansWidth %d, ansHeight %d\n", propWidth, propHeight, answer->width, answer->height);*/ if (propWidth == answer->width && propHeight == answer->height) return XtGeometryYes; else if (answer->width == curWidth && answer->height == curHeight) return XtGeometryNo; else return XtGeometryAlmost;} /*** Set the text buffer which this widget will display and interact with.** The currently attached buffer is automatically freed, ONLY if it has** no additional modify procs attached (as it would if it were being** displayed by another text widget).*/void TextSetBuffer(Widget w, textBuffer *buffer){ textBuffer *oldBuf = ((TextWidget)w)->text.textD->buffer; StopHandlingXSelections(w); TextDSetBuffer(((TextWidget)w)->text.textD, buffer); if (oldBuf->nModifyProcs == 0) BufFree(oldBuf);}/*** Get the buffer associated with this text widget. Note that attaching** additional modify callbacks to the buffer will prevent it from being** automatically freed when the widget is destroyed.*/textBuffer *TextGetBuffer(Widget w){ return ((TextWidget)w)->text.textD->buffer;}/*** Translate a line number and column into a position*/int TextLineAndColToPos(Widget w, int lineNum, int column){ return TextDLineAndColToPos(((TextWidget)w)->text.textD, lineNum, column );}/*** Translate a position into a line number (if the position is visible,** if it's not, return False*/int TextPosToLineAndCol(Widget w, int pos, int *lineNum, int *column){ return TextDPosToLineAndCol(((TextWidget)w)->text.textD, pos, lineNum, column);}/*** Translate a buffer text position to the XY location where the center** of the cursor would be positioned to point to that character. Returns** False if the position is not displayed because it is VERTICALLY out** of view. If the position is horizontally out of view, returns the** x coordinate where the position would be if it were visible.*/int TextPosToXY(Widget w, int pos, int *x, int *y){ return TextDPositionToXY(((TextWidget)w)->text.textD, pos, x, y);}/*** Return the cursor position*/int TextGetCursorPos(Widget w){ return TextDGetInsertPosition(((TextWidget)w)->text.textD);}/*** Set the cursor position*/void TextSetCursorPos(Widget w, int pos){ TextDSetInsertPosition(((TextWidget)w)->text.textD, pos); checkAutoShowInsertPos(w); callCursorMovementCBs(w, NULL);}/*** Return the horizontal and vertical scroll positions of the widget*/void TextGetScroll(Widget w, int *topLineNum, int *horizOffset)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -