📄 scrolltext.c
字号:
textInfo->numLines = linenum+1; if (startPos == 0) { textInfo->startLine = 0; } textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); textInfo->curLine = linenum; /* Check to see if we are at the bottom */ if (textInfo->endLine >= textInfo->numLines-1) { textInfo->curY = textInfo->h - textInfo->bottomSpace - lineptr->lineHeight; textInfo->flagWord &= (~NOTATBOTTOM); } else { textInfo->flagWord |= NOTATBOTTOM; } return 1;}int TxtAddFont(display, textWin, fontNumber, newFont, newColor)Display *display;Window textWin; /* Scrollable text window */int fontNumber; /* Place to add font (0-7) */XFontStruct *newFont; /* Font to add */int newColor; /* Color of font *//* * This routine loads a new font so that it can be used in a previously * created text window. There are eight font slots numbered 0 through 7. * If there is already a font in the specified slot, it will be replaced * and an automatic redraw of the window will take place. See TxtWriteStr * for details on using alternate fonts. The color specifies the foreground * color of the text. The default foreground color is used if this * parameter is TXT_NO_COLOR. Returns a non-zero value if * everything went well. */{ struct txtWin *textInfo; int redrawFlag; XGCValues gc_val; if ((fontNumber < 0) || (fontNumber >= MAXFONTS)) return 0; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) textWin)) == 0) return 0; if (newColor == TXT_NO_COLOR) { newColor = textInfo->fgPix; } gc_val.font = newFont->fid; gc_val.foreground = newColor; gc_val.background = textInfo->bgPix; gc_val.plane_mask = AllPlanes; gc_val.graphics_exposures = 1; gc_val.function = GXcopy; if (textInfo->fontGC[fontNumber] != 0) { XChangeGC(display, textInfo->fontGC[fontNumber], GCFont | GCForeground, &gc_val); } else textInfo->fontGC[fontNumber] = XCreateGC(display, textWin, GCFont | GCForeground | GCBackground | GCFunction | GCPlaneMask | GCGraphicsExposures, &gc_val); redrawFlag = (textInfo->theFonts[fontNumber].fid != 0) && (((newFont) && (newFont->fid != textInfo->theFonts[fontNumber].fid)) || (newColor != textInfo->theColors[fontNumber])); if (newFont) { textInfo->theFonts[fontNumber] = *newFont; } textInfo->theColors[fontNumber] = newColor; if (redrawFlag) { RecompBuffer(textInfo); XClearWindow(display, textWin); TxtRepaint(display, textWin); } return 1;}int TxtWinP(display, w)Display *display;Window w;/* * Returns a non-zero value if the window has been previously grabbed * using TxtGrab and 0 if it has not. */{ if (XLookUpAssoc(display, textWindows, (XID) w)) return(1); else return(0);}static int FindEndLine(textInfo, botSpace)struct txtWin *textInfo;int *botSpace;/* * Given the starting line in 'textInfo->startLine', this routine * determines the index of the last line that can be drawn given the * current size of the screen. If there are not enough lines to * fill the screen, the index of the last line will be returned. * The amount of empty bottom space is returned in 'botSpace'. */{ int index, height, lineHeight; height = YPADDING; index = textInfo->startLine; while (index < textInfo->numLines) { lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; if (height + lineHeight > textInfo->h) break; height += lineHeight; index++; } if (botSpace) { *botSpace = textInfo->h - height; } return index - 1;}static int UpdateScroll(display, textInfo)Display *display;struct txtWin *textInfo; /* Text window information *//* * This routine computes the current extent of the scroll bar * indicator and repaints the bar with the correct information. */{ int top, bottom; if (textInfo->numLines > 1) { top = textInfo->startLine * (textInfo->h - 2*BARBORDER) / (textInfo->numLines - 1); bottom = textInfo->endLine * (textInfo->h - 2*BARBORDER) / (textInfo->numLines - 1); } else { top = 0; bottom = textInfo->h - (2*BARBORDER); } /* Draw it - make sure there is a little padding */ if (top == 0) top++; if (bottom == textInfo->h-(2*BARBORDER)) bottom--; XFillRectangle(display, textInfo->scrollBar, textInfo->bgGC, 0, 0, BARSIZE, top-1); XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC, top, BARSIZE - (2*BARBORDER) - 2, bottom - top); XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC, 0, bottom+1, BARSIZE, textInfo->h - (2 * BARBORDER) - bottom); return 1;}int TxtClear(display, w)Display *display;Window w;/* * This routine clears a scrollable text window. It resets the current * writing position to the upper left hand corner of the screen. * NOTE: THIS ALSO CLEARS THE CONTENTS OF THE TEXT WINDOW BUFFER AND * RESETS THE SCROLL BAR. Returns 0 if the window is not a text window. * This should be used *instead* of XClear. */{ struct txtWin *textInfo; int index; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) return 0; /* Zero out the arrays */ textInfo->bufSpot = 0; for (index = 0; index < textInfo->numLines; index++) { InitLine(textInfo->txtBuffer[index]); } textInfo->txtBuffer[0]->lineHeight = textInfo->theFonts[textInfo->curFont].ascent + textInfo->theFonts[textInfo->curFont].descent; textInfo->numLines = 1; textInfo->startLine = 0; textInfo->endLine = 0; textInfo->curLine = 0; textInfo->curX = 0; textInfo->curY = YPADDING + textInfo->theFonts[textInfo->curFont].ascent + textInfo->theFonts[textInfo->curFont].descent; textInfo->bottomSpace = textInfo->h - YPADDING - textInfo->theFonts[textInfo->curFont].ascent - INTERLINE - textInfo->theFonts[textInfo->curFont].descent; /* Actually clear the window */ XClearWindow(display, w); /* Draw the current cursor */ XFillRectangle(display, w, textInfo->CursorGC, XPADDING + CUROFFSET, textInfo->curY, CURSORWIDTH, textInfo->theFonts[textInfo->curFont].ascent + textInfo->theFonts[textInfo->curFont].descent); /* Update the scroll bar */ UpdateScroll(display, textInfo); return 1;}static int WarpToBottom(display, textInfo)Display *display;struct txtWin *textInfo; /* Text Information *//* * This routine causes the specified text window to display its * last screen of information. It updates the scroll bar * to the appropriate spot. The implementation scans backward * through the buffer to find an appropriate starting spot for * the window. */{ int index, height, lineHeight; index = textInfo->numLines-1; height = 0; while (index >= 0) { lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; if (height + lineHeight > textInfo->h) break; height += lineHeight; index--; } textInfo->startLine = index + 1; textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); textInfo->curY = textInfo->h - textInfo->bottomSpace - textInfo->txtBuffer[textInfo->endLine]->lineHeight; XClearWindow(display, textInfo->mainWindow); TxtRepaint(display, textInfo->mainWindow); return 1;}static int UpdateExposures(display, textInfo)Display *display;struct txtWin *textInfo; /* Text window information *//* * Before a new scrolling action occurs, the text window package * must handle all COPYEXPOSE events generated by the last scrolling * action. This routine is called to do this. Foreign events (those * not handled by TxtFilter) are queued up and replaced on the queue * after the processing of the exposure events is complete. */{#if 0 XEvent foreignQueue[MAXFOREIGN]; int index, lastItem = 0; while (textInfo->flagWord & COPYEXPOSE) { XNextEvent(display, &(foreignQueue[lastItem])); if (!TxtFilter(display, &(foreignQueue[lastItem]))) lastItem++; if (lastItem >= MAXFOREIGN) { printf("Too many foreign events to queue!\n"); textInfo->flagWord &= (~COPYEXPOSE); } } for (index = 0; index < lastItem; index++) { XPutBackEvent(display, &(foreignQueue[index])); }#endif return 1;}static int ScrollDown(display,textInfo)Display *display;struct txtWin *textInfo; /* Text window information *//* * This routine scrolls the indicated text window down by one * line. The line below the current line must exist. The window * is scrolled so that the line below the last line is fully * displayed. This may cause many lines to scroll off the top. * Scrolling is done using XCopyArea. The exposure events should * be caught using ExposeCopy. */{ int lineSum, index, targetSpace, freeSpace, updateFlag; lineSum = 0; if (textInfo->endLine + 1 >= textInfo->numLines) return 0; targetSpace = textInfo->txtBuffer[textInfo->endLine+1]->lineHeight + INTERLINE; if (textInfo->bottomSpace < targetSpace) { index = textInfo->startLine; while (index < textInfo->endLine) { lineSum += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); if (textInfo->bottomSpace + lineSum >= targetSpace) break; index++; } /* Must move upward by 'lineSum' pixels */ XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, DEFAULT_GC, 0, lineSum, textInfo->w - BARSIZE, textInfo->h, 0, 0); textInfo->flagWord |= COPYEXPOSE; /* Repair the damage to the structures */ textInfo->startLine = index + 1; updateFlag = 1; } else { updateFlag = 0; } /* More lines might be able to fit. Let's check. */ freeSpace = textInfo->bottomSpace + lineSum - targetSpace; index = textInfo->endLine + 1; while (index < textInfo->numLines-1) { if (freeSpace - textInfo->txtBuffer[index+1]->lineHeight - INTERLINE < 0) break; freeSpace -= (textInfo->txtBuffer[index+1]->lineHeight + INTERLINE); index++; } textInfo->endLine = index; textInfo->bottomSpace = freeSpace; if (updateFlag) { UpdateExposures(display, textInfo); } UpdateScroll(display, textInfo); return 1;}static int ExpandLines(textInfo)struct txtWin *textInfo; /* Text Information *//* * This routine allocates and initializes additional space in * the line start array (txtBuffer). The new space * is allocated using realloc. The expansion factor is a percentage * given by EXPANDPERCENT. */{ int newSize, index; newSize = textInfo->allocLines; newSize += (newSize * EXPANDPERCENT) / 100; textInfo->txtBuffer = (struct txtLine **) realloc((char *) textInfo->txtBuffer, (unsigned) (newSize * sizeof(struct txtLine *))); for (index = textInfo->allocLines; index < newSize; index++) { textInfo->txtBuffer[index] = alloc(struct txtLine); InitLine(textInfo->txtBuffer[index]); } textInfo->allocLines = newSize; return 1;}static int ExpandBuffer(textInfo)struct txtWin *textInfo; /* Text information *//* * Expands the basic character buffer using realloc. The expansion * factor is a percentage given by EXPANDPERCENT. */{ int newSize; newSize = textInfo->bufAlloc + (textInfo->bufAlloc * EXPANDPERCENT) / 100; textInfo->mainBuffer = (short *) realloc((char *) textInfo->mainBuffer, (unsigned) newSize * sizeof(short)); textInfo->bufAlloc = newSize; return 1;}static int HandleNewLine(display, textInfo, flagWord)Display *display;struct txtWin *textInfo; /* Text Information */int flagWord; /* DODISP or NONEWLINE or both *//* * This routine initializes the next line for drawing by setting * its height to the current font height, scrolls the screen down * one line, and updates the current drawing position to the * left edge of the newly cleared line. If DODISP is specified, * the screen will be updated (otherwise not). If NONEWLINE is * specified, no newline character will be added to the text buffer * (this is for line wrap). */{ struct txtLine *curLine, *nextLine; /* Check to see if a new line must be allocated */ if (textInfo->curLine >= textInfo->allocLines-1) /* Expand the number of lines */ ExpandLines(textInfo); textInfo->numLines += 1; /* Then we initialize the next line */ nextLine = textInfo->txtBuffer[textInfo->numLines-1]; nextLine->lineHeight = textInfo->theFonts[textInfo->curFont].ascent + textInfo->theFonts[textInfo->curFont].descent; curLine = textInfo->txtBuffer[textInfo->curLine]; if (flagWord & DODISP) { /* Scroll down a line if required */ if ((textInfo->curY + curLine->lineHeight + nextLine->lineHeight + (INTERLINE * 2)) > textInfo->h) { ScrollDown(display, textInfo); } else { /* Update the bottom space appropriately */ textInfo->bottomSpace -= (nextLine->lineHeight + INTERLINE); textInfo->endLine += 1; } /* Update drawing position */ textInfo->curY = textInfo->h - (textInfo->bottomSpace + nextLine->lineHeight); } /* Move down a line */ textInfo->curLine += 1; if (!(flagWord & NONEWLINE)) { /* Append end-of-line to text buffer */ if (textInfo->bufSpot >= textInfo->bufAlloc) { /* Allocate more space in main text buffer */ ExpandBuffer(textInfo); } textInfo->mainBuffer[(textInfo->bufSpot)++] = (textInfo->curFont << FONTSHIFT) | '\n'; } nextLine->lineText = textInfo->bufSpot; textInfo->curX = 0; return 1;}static int CharSize(textInfo, lineNum, charNum)struct txtWin *textInfo; /* Current Text Information */int lineNum; /* Line in buffer */int charNum; /* Character in line *//* * This routine determines the size of the specified character.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -