📄 scrolltext.c
字号:
if (*str <= thisFont->min_char_or_byte2 || *str >= thisFont->max_char_or_byte2 || thisFont->per_char == 0) charWidth = thisFont->max_bounds.width + 1; else charWidth = thisFont->per_char[*str].width + 1; /* Check to see if line wrap is required */ thisLine = textInfo->txtBuffer[textInfo->curLine]; if (thisLine->lineWidth + charWidth > (textInfo->w-BARSIZE-WRAPINDSIZE)) { thisLine->lineFlags |= WRAPFLAG; /* Handle the spacing problem the same way as a newline */ HandleNewLine(display, textInfo, NONEWLINE); thisLine = textInfo->txtBuffer[textInfo->curLine]; } /* Append character onto main buffer */ if (textInfo->bufSpot >= textInfo->bufAlloc) /* Make room for more characters */ ExpandBuffer(textInfo); textInfo->mainBuffer[(textInfo->bufSpot)++] = (textInfo->curFont << FONTSHIFT) | (*str); /* Update the line start array */ thisLine->lineLength += 1; thisLine->lineWidth += charWidth; } else if (*str == NEWLINE) { HandleNewLine(display, textInfo, 0); } else if (*str == NEWFONT) { /* Go into waiting for font number mode */ textInfo->flagWord |= FONTNUMWAIT; } else if (*str == BACKSPACE) { HandleBackspace(display, textInfo, 0); } else { /* Ignore all others */ } } textInfo->flagWord |= SCREENWRONG; return 1;}int TxtRepaint(display,w)Display *display;Window w;/* * Repaints the given scrollable text window. The routine repaints * the entire window. For handling exposure events, the TxtFilter * routine should be used. */{ struct txtWin *textInfo; int index, ypos; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) ) == 0) return 0; /* Check to see if the screen is up to date */ if (textInfo->flagWord & SCREENWRONG) { textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); textInfo->flagWord &= (~SCREENWRONG); } ypos = YPADDING; index = textInfo->startLine; for (;;) { DrawLine(display, textInfo, index, ypos); if (index >= textInfo->endLine) break; ypos += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); index++; } /* Draw the cursor (if on screen) */ if (textInfo->endLine == textInfo->curLine) { XFillRectangle(display, w, textInfo->CursorGC, textInfo->txtBuffer[index]->lineWidth + CUROFFSET, ypos /* + textInfo->txtBuffer[index]->lineHeight */, CURSORWIDTH, textInfo->txtBuffer[index]->lineHeight); } /* Update the scroll bar */ UpdateScroll(display, textInfo); return 1;}static int InsertIndex(textInfo, thisIndex, ypos)struct txtWin *textInfo; /* Text Window Information */int thisIndex; /* Line index of exposed line */int ypos; /* Drawing position of line *//* * This routine inserts the supplied line index into the copy * exposure array for 'textInfo'. The array is kept sorted * from lowest to highest using insertion sort. The array * is dynamically expanded if needed. */{ struct expEvent *newItem; int newSize, index, downIndex; /* Check to see if we need to expand it */ if ((textInfo->exposeSize + 3) >= textInfo->exposeAlloc) { newSize = textInfo->exposeAlloc + (textInfo->exposeAlloc * EXPANDPERCENT / 100); textInfo->exposeAry = (struct expEvent **) realloc((char *) textInfo->exposeAry, (unsigned) (newSize * sizeof(struct expEvent *))); for (index = textInfo->exposeAlloc; index < newSize; index++) textInfo->exposeAry[index] = alloc(struct expEvent); textInfo->exposeAlloc = newSize; } /* Find spot for insertion. NOTE: last spot has big number */ for (index = 0; index <= textInfo->exposeSize; index++) { if (textInfo->exposeAry[index]->lineIndex >= thisIndex) { if (textInfo->exposeAry[index]->lineIndex > thisIndex) { /* Insert before this entry */ newItem = textInfo->exposeAry[textInfo->exposeSize+1]; for (downIndex = textInfo->exposeSize; downIndex >= index; downIndex--) { textInfo->exposeAry[downIndex+1] = textInfo->exposeAry[downIndex]; } /* Put a free structure at this spot */ textInfo->exposeAry[index] = newItem; /* Fill it in */ textInfo->exposeAry[index]->lineIndex = thisIndex; textInfo->exposeAry[index]->ypos = ypos; /* Break out of loop */ textInfo->exposeSize += 1; } break; } } return 1;}static int ScrollUp(display, textInfo)Display *display;struct txtWin *textInfo; /* Text window information *//* * This routine scrolls the indicated text window up by one * line. The line above the current line must exist. The * window is scrolled so that the line above the start line * is displayed at the top of the screen. This may cause * many lines to scroll off the bottom. The scrolling is * done using XCopyArea. The exposure events should be caught * by ExposeCopy. */{ int targetSpace; /* Make sure all exposures have been handled by now */ if (textInfo->startLine == 0) return 0; targetSpace = textInfo->txtBuffer[textInfo->startLine-1]->lineHeight + INTERLINE; /* Move the area downward by the target amount */ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, DEFAULT_GC, 0, YPADDING, textInfo->w - BARSIZE, textInfo->h, 0, targetSpace); textInfo->flagWord |= COPYEXPOSE; /* Update the text window parameters */ textInfo->startLine -= 1; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); /* Clear out bottom space region */ XClearArea(display, textInfo->mainWindow, 0, textInfo->h - textInfo->bottomSpace, textInfo->w, textInfo->bottomSpace); UpdateExposures(display, textInfo); UpdateScroll(display, textInfo); return 1;}static int ScrollToSpot(display, textInfo, ySpot)Display *display;struct txtWin *textInfo; /* Text window information */int ySpot; /* Button position in scroll window *//* * This routine scrolls the specified text window relative to the * position of the mouse in the scroll bar. The center of the screen * will be positioned to correspond to the mouse position. */{ int targetLine, aboveLines; targetLine = textInfo->numLines * ySpot / textInfo->h; textInfo->startLine = targetLine; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); aboveLines = 0; /* Make the target line the *center* of the window */ while ((textInfo->startLine > 0) && (aboveLines < textInfo->endLine - targetLine)) { textInfo->startLine -= 1; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); aboveLines++; } if (textInfo->endLine == textInfo->numLines-1) { WarpToBottom(display, textInfo); } else { XClearWindow(display, textInfo->mainWindow); TxtRepaint(display, textInfo->mainWindow); } return 1;}static int LineToTop(display, textInfo, pos)Display *display;struct txtWin *textInfo; /* Text window information */int pos; /* Y position of mouse *//* * This routine scrolls the screen down until the line at the * mouse position is at the top of the screen. It stops * if it can't scroll the buffer down that far. If the * global 'ScrollOption' is NORMSCROLL, a smooth scroll * is used. Otherwise, it jumps to the right position * and repaints the screen. */{ int index, sum; /* First, we find the current line */ sum = 0; for (index = textInfo->startLine; index <= textInfo->endLine; index++) { if (sum + textInfo->txtBuffer[index]->lineHeight + INTERLINE> pos) break; sum += textInfo->txtBuffer[index]->lineHeight + INTERLINE; } /* We always want to scroll down at least one line */ if (index == textInfo->startLine) index++; if (ScrollOption == NORMSCROLL) { /* Scroll down until 'index' is the starting line */ while ((textInfo->startLine < index) && ScrollDown(display, textInfo)) { /* Empty Loop Body */ } } else { /* Immediately jump to correct spot */ textInfo->startLine = index; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); if (textInfo->endLine == textInfo->numLines-1) { WarpToBottom(display, textInfo); } else { XClearWindow(display, textInfo->mainWindow); TxtRepaint(display, textInfo->mainWindow); } } /* Check to see if at end of buffer */ if (textInfo->endLine >= textInfo->numLines-1) { textInfo->flagWord &= (~NOTATBOTTOM); } return 1;}static int TopToHere(display, textInfo, pos)Display *display;struct txtWin *textInfo; /* Text window information */int pos; /* Y position of mouse *//* * This routine scrolls the screen up until the top line of * the screen is at the current Y position of the mouse. Again, * it will stop if it can't scroll that far. If the global * 'ScrollOption' is NORMSCROLL, a smooth scroll is used. * If it's not, it will simply redraw the screen at the * correct spot. */{ int sum, target, linesup, index; target = pos - textInfo->txtBuffer[textInfo->startLine]->lineHeight; /* We always want to scroll up at least one line */ if (target <= 0) target = 1; sum = 0; linesup = 0; /* Check to see if we are at the top anyway */ if (textInfo->startLine == 0) return 0; if (ScrollOption == NORMSCROLL) { /* Scroll up until sum of new top lines greater than target */ while ((sum < target) && ScrollUp(display, textInfo)) { sum += textInfo->txtBuffer[textInfo->startLine]->lineHeight; linesup++; } } else { /* Search backward to find index */ index = textInfo->startLine - 1; while ((index > 0) && (sum < target)) { sum += textInfo->txtBuffer[index]->lineHeight; linesup++; index--; } /* Go directly to the index */ textInfo->startLine = index; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); XClearWindow(display, textInfo->mainWindow); TxtRepaint(display, textInfo->mainWindow); } /* If we scrolled, assert we are not at bottom of buffer */ if (linesup > 0) { textInfo->flagWord |= NOTATBOTTOM; } return 1;}int TxtFilter(display, evt)Display *display;XEvent *evt;/* * This routine handles events associated with scrollable text windows. * It will handle all exposure events and any button released events * in the scroll bar of a text window. It does NOT handle any other * events. If it cannot handle the event, it will return 0. */{ XExposeEvent *expose = &evt->xexpose; XButtonEvent *btEvt = &evt->xbutton; XGraphicsExposeEvent *gexpose = &evt->xgraphicsexpose; XNoExposeEvent *noexpose = &evt->xnoexpose; struct txtWin *textInfo; int index, ypos; Window w, sw; if (textWindows == (XAssocTable *) 0) { textWindows = XCreateAssocTable(32); if (textWindows == (XAssocTable *) 0) return(0); } if (evt->type == Expose) { w = expose->window; sw = 0; } else if (evt->type == GraphicsExpose) { w = gexpose->drawable; sw = 0; } else if (evt->type == NoExpose) { w = noexpose->drawable; sw = 0; } else if (evt->type == ButtonRelease) { w = btEvt->window; sw = btEvt->subwindow; } else return 0; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) return 0; /* Determine whether it's main window or not */ if ((w == textInfo->mainWindow) && (sw == 0)) { /* Main Window - handle exposures */ switch (evt->type) { case Expose: ypos = 0 /*YPADDING*/; for (index = textInfo->startLine; index <= textInfo->endLine; index++) { int lh = textInfo->txtBuffer[index]->lineHeight; if (((ypos + lh) >= expose->y) && (ypos <= (expose->y + expose->height))) { /* Intersection region */ /* Draw line immediately */ DrawLine(display, textInfo, index, ypos); /* And possibly draw cursor */ if (textInfo->curLine == index) { XFillRectangle(display, w, textInfo->CursorGC, textInfo->txtBuffer[index]->lineWidth + CUROFFSET, ypos, CURSORWIDTH, lh); } } ypos += lh + INTERLINE; } break; case GraphicsExpose: ypos = 0 /*YPADDING*/; for (index = textInfo->startLine; index <= textInfo->endLine; index++) { int lh = textInfo->txtBuffer[index]->lineHeight; if (((ypos + lh) >= gexpose->y) && (ypos <= (gexpose->y + gexpose->height))) { /* Intersection region */ /* Draw line immediately */ DrawLine(display, textInfo, index, ypos); /* And possibly draw cursor */ if (textInfo->curLine == index) { XFillRectangle(display, w, textInfo->CursorGC, textInfo->txtBuffer[index]->lineWidth + CUROFFSET, ypos, CURSORWIDTH, lh); } } ypos += lh + INTERLINE; } break; case NoExpose: break; default: /* Not one of our events */ return 0; } } else { switch (evt->type) { case Expose: UpdateScroll(display, textInfo); break; case ButtonRelease: /* Find out which button */ switch (btEvt->button) { case Button1: /* Scroll up until top line is at mouse position */ TopToHere(display, textInfo, btEvt->y); break; case Button2: /* Scroll to spot relative to position */ ScrollToSpot(display, textInfo, btEvt->y); if (textInfo->endLine >= textInfo->numLines-1) { textInfo->flagWord &= (~NOTATBOTTOM); } else { textInfo->flagWord |= NOTATBOTTOM; } break; case Button3: /* Scroll down until pointed line is at top */ LineToTop(display, textInfo, btEvt->y); break; } break; default: /* Not one of our events */ return 0; } } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -