📄 scrolltext.c
字号:
* It takes in account the font of the character and whether its * fixed or variable. The size includes INTERSPACE spacing between * the characters. */{ register XFontStruct *charFont; register short *theLine; register short theChar; theLine = &(textInfo->mainBuffer[textInfo->txtBuffer[lineNum]->lineText]); theChar = theLine[charNum] & CHARMASK; charFont = &(textInfo->theFonts[(theChar & FONTMASK) >> FONTSHIFT]); if (theChar <= charFont->min_char_or_byte2 || theChar >= charFont->max_char_or_byte2 || charFont->per_char == 0) return charFont->max_bounds.width + 1; else return charFont->per_char[theChar].width + 1;}static int HandleBackspace(display, textInfo, flagWord)Display *display;struct txtWin *textInfo; /* Text Information */int flagWord; /* DODISP or nothing *//* * This routine handles a backspace found in the input stream. The * character before the current writing position will be erased and * the drawing position will move back one character. If the writing * position is at the left margin, the drawing position will move * up to the previous line. If it is a line that has been wrapped, * the character at the end of the previous line will be erased. */{ struct txtLine *thisLine, *prevLine; int chSize; thisLine = textInfo->txtBuffer[textInfo->curLine]; /* First, determine whether we need to go back a line */ if (thisLine->lineLength == 0) { /* Bleep if at top of buffer */ if (textInfo->curLine == 0) { XBell(display, 50); return 0; } /* See if we have to scroll in the other direction */ if ((flagWord & DODISP) && (textInfo->curY <= YPADDING)) { /* This will display the last lines of the buffer */ WarpToBottom(display, textInfo); } /* Set drawing position at end of previous line */ textInfo->curLine -= 1; prevLine = textInfo->txtBuffer[textInfo->curLine]; textInfo->numLines -= 1; if (flagWord & DODISP) { textInfo->curY -= (prevLine->lineHeight + INTERLINE); textInfo->bottomSpace += (thisLine->lineHeight + INTERLINE); textInfo->endLine -= 1; } /* We are unlinewrapping if the previous line has flag set */ if (prevLine->lineFlags & WRAPFLAG) { /* Get rid of line wrap indicator */ if (flagWord & DODISP) { XFillRectangle(display, textInfo->mainWindow, textInfo->bgGC, textInfo->w - BARSIZE - WRAPINDSIZE, textInfo->curY, WRAPINDSIZE, prevLine->lineHeight); } prevLine->lineFlags &= (~WRAPFLAG); /* Call recursively to wipe out the ending character */ HandleBackspace(display, textInfo, flagWord); } else { /* Delete the end-of-line in the primary buffer */ textInfo->bufSpot -= 1; } } else { /* Normal deletion of character */ chSize = CharSize(textInfo, textInfo->curLine, textInfo->txtBuffer[textInfo->curLine]->lineLength - 1); /* Move back appropriate amount and wipe it out */ thisLine->lineWidth -= chSize; if (flagWord & DODISP) { XFillRectangle(display, textInfo->mainWindow, textInfo->bgGC, thisLine->lineWidth, textInfo->curY, chSize, thisLine->lineHeight); } /* Delete from buffer */ textInfo->txtBuffer[textInfo->curLine]->lineLength -= 1; textInfo->bufSpot -= 1; } return 1;}static int DrawLineWrap(display, win, x, y, h, col)Display *display;Window win; /* What window to draw it in */int x, y; /* Position of upper left corner */int h; /* Height of indicator */int col; /* Color of indicator *//* * This routine draws a line wrap indicator at the end of a line. * Visually, it is an arrow of the specified height directly against * the scroll bar border. The bitmap used for the arrow is stored * in 'arrowMap' with size 'arrow_width' and 'arrow_height'. */{ struct txtWin *textInfo; textInfo = (struct txtWin *)XLookUpAssoc(display, textWindows, (XID) win); /* First, draw the arrow */ XCopyArea(display, textInfo->arrowMap, textInfo->mainWindow, textInfo->CursorGC, 0, 0, arrow_width, arrow_height, x, y + h - arrow_height, 1); /* Then draw the stem */ XDrawLine(display, textInfo->mainWindow, textInfo->CursorGC, x + STEMOFFSET, y, x + STEMOFFSET, y + h - arrow_height); return 1;}static int DrawLine(display, textInfo, lineIndex, ypos)Display *display;struct txtWin *textInfo; /* Text window information */int lineIndex; /* Index of line to draw */int ypos; /* Y position for line *//* * This routine destructively draws the indicated line in the * indicated window at the indicated position. It does not * clear to end of line however. It draws a line wrap indicator * if needed but does not draw a cursor. */{ int index, startPos, curFont, theColor, curX, saveX, fontIndex; struct txtLine *someLine; char lineBuffer[BUFSIZE], *glyph; short *linePointer; XFontStruct *theFont; XGCValues gc; /* First, we draw the text */ index = 0; curX = XPADDING; someLine = textInfo->txtBuffer[lineIndex]; linePointer = &(textInfo->mainBuffer[someLine->lineText]); while (index < someLine->lineLength) { startPos = index; saveX = curX; curFont = linePointer[index] & FONTMASK; fontIndex = curFont >> FONTSHIFT; theFont = &(textInfo->theFonts[fontIndex]); theColor = textInfo->theColors[fontIndex]; glyph = &(lineBuffer[0]); while ((index < someLine->lineLength) && ((linePointer[index] & FONTMASK) == curFont)) { *glyph = linePointer[index] & CHARMASK; index++; curX += CharSize(textInfo, lineIndex, index); glyph++; } /* Flush out the glyphs */ XFillRectangle(display, textInfo->mainWindow, textInfo->bgGC, saveX, ypos, textInfo->w - BARSIZE, someLine->lineHeight + YPADDING + INTERLINE); XDrawString(display, textInfo->mainWindow, textInfo->fontGC[fontIndex], saveX, ypos, lineBuffer, someLine->lineLength); } /* Then the line wrap indicator (if needed) */ if (someLine->lineFlags & WRAPFLAG) { DrawLineWrap(display, textInfo->mainWindow, textInfo->w - BARSIZE - WRAPINDSIZE, ypos, someLine->lineHeight, textInfo->fgPix); } return 1;}static int HandleNewFont(display, fontNum, textInfo, flagWord)Display *display;int fontNum; /* Font number */struct txtWin *textInfo; /* Text information */int flagWord; /* DODISP or nothing *//* * This routine handles a new font request. These requests take * the form "^F<digit>". The parsing is done in TxtWriteStr. * This routine is called only if the form is valid. It may return * a failure (0 status) if the requested font is not loaded. * If the new font is larger than any of the current * fonts on the line, it will change the line height and redisplay * the line. */{ struct txtLine *thisLine; int heightDiff, baseDiff, redrawFlag; if (textInfo->theFonts[fontNum].fid == 0) { return 0; } else { thisLine = textInfo->txtBuffer[textInfo->curLine]; textInfo->curFont = fontNum; redrawFlag = 0; heightDiff = textInfo->theFonts[fontNum].ascent + textInfo->theFonts[fontNum].descent - thisLine->lineHeight; if (heightDiff > 0) { redrawFlag = 1; } else { heightDiff = 0; } if (redrawFlag) { if (flagWord & DODISP) { /* Clear current line */ XFillRectangle(display, textInfo->mainWindow, textInfo->bgGC, 0, textInfo->curY, textInfo->w, thisLine->lineHeight); /* Check to see if it requires scrolling */ if ((textInfo->curY + thisLine->lineHeight + heightDiff + INTERLINE) > textInfo->h) { /* * General approach: "unscroll" the last line up * and then call ScrollDown to do the right thing. */ textInfo->endLine -= 1; textInfo->bottomSpace += thisLine->lineHeight + INTERLINE; XFillRectangle(display, textInfo->mainWindow, textInfo->bgGC, 0, textInfo->h - textInfo->bottomSpace, textInfo->w, textInfo->bottomSpace); thisLine->lineHeight += heightDiff; ScrollDown(display, textInfo); textInfo->curY = textInfo->h - (textInfo->bottomSpace + INTERLINE + thisLine->lineHeight); } else { /* Just update bottom space */ textInfo->bottomSpace -= heightDiff; thisLine->lineHeight += heightDiff; } /* Redraw the current line */ DrawLine(display, textInfo, textInfo->curLine, textInfo->curY); } else { /* Just update line height */ thisLine->lineHeight += heightDiff; } } return 1; }}int TxtWriteStr(display, w, str)Display *display;Window w; /* Text window */register char *str; /* 0 terminated string *//* * This routine writes a string to the specified text window. * The following notes apply: * - Text is always appended to the end of the text buffer. * - If the scroll bar is positioned such that the end of the * text is not visible, an automatic scroll to the bottom * will be done before the appending of text. * - Non-printable ASCII characters are not displayed. * - The '\n' character causes the current text position to * advance one line and start at the left. * - Tabs are not supported. * - Lines too long for the screen will be wrapped and a line wrap * indication will be drawn. * - Backspace clears the previous character. It will do the right * thing if asked to backspace past a wrapped line. * - A new font can be chosen using the sequence '^F<digit>' where * <digit> is 0-7. The directive will be ignored if * there is no font in the specified slot. * Returns 0 if something went wrong. */{ register int fontIndex; register struct txtWin *textInfo; register struct txtLine *thisLine; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) return 0; /* See if screen needs to be updated */ if (textInfo->flagWord & SCREENWRONG) { TxtRepaint(display, textInfo->mainWindow); } /* See if we have to scroll down to the bottom */ if (textInfo->flagWord & NOTATBOTTOM) { WarpToBottom(display, textInfo); textInfo->flagWord &= (~NOTATBOTTOM); } /* Undraw the current cursor */ thisLine = textInfo->txtBuffer[textInfo->curLine]; XFillRectangle(display, w, textInfo->bgGC, thisLine->lineWidth + CUROFFSET, textInfo->curY, CURSORWIDTH, thisLine->lineHeight); for ( /* str is ok */ ; (*str != 0) ; str++) { /* Check to see if we are waiting on a font */ if (textInfo->flagWord & FONTNUMWAIT) { textInfo->flagWord &= (~FONTNUMWAIT); fontIndex = *str - '0'; if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { /* Handle font -- go get next character */ if (HandleNewFont(display, fontIndex, textInfo, DODISP)) continue; } } /* Inline code for handling normal character case */ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { register XFontStruct *thisFont; register struct txtLine *thisLine; register int charWidth; int thisColor; /* Determine size of character */ thisFont = &(textInfo->theFonts[textInfo->curFont]); thisColor = textInfo->theColors[textInfo->curFont]; 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)) { DrawLineWrap(display, textInfo->mainWindow, textInfo->w-BARSIZE-WRAPINDSIZE, textInfo->curY, thisLine->lineHeight, textInfo->fgPix); thisLine->lineFlags |= WRAPFLAG; /* Handle the spacing problem the same way as a newline */ HandleNewLine(display, textInfo, DODISP | NONEWLINE); thisLine = textInfo->txtBuffer[textInfo->curLine]; } /* Ready to draw character */ XDrawString(display, textInfo->mainWindow, DEFAULT_GC, textInfo->curX += charWidth, textInfo->curY + thisLine->lineHeight, str, 1); /* 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, DODISP); } else if (*str == NEWFONT) { /* Go into waiting for font number mode */ textInfo->flagWord |= FONTNUMWAIT; } else if (*str == BACKSPACE) { HandleBackspace(display, textInfo, DODISP); } else { /* Ignore all others */ } } /* Draw the cursor in its new position */ thisLine = textInfo->txtBuffer[textInfo->curLine]; XFillRectangle(display, w, textInfo->CursorGC, thisLine->lineWidth + CUROFFSET, textInfo->curY /* + thisLine->lineHeight */, CURSORWIDTH, thisLine->lineHeight); return 1;}int TxtJamStr(display, w, str)Display *display;Window w; /* Text window */register char *str; /* NULL terminated string *//* * This is the same as TxtWriteStr except the screen is NOT updated. * After a call to this routine, TxtRepaint should be called to * update the screen. This routine is meant to be used to load * a text buffer with information and then allow the user to * scroll through it at will. */{ register int fontIndex; register struct txtWin *textInfo; if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) ) == 0) return 0; for ( /* str is ok */ ; (*str != 0) ; str++) { /* Check to see if we are waiting on a font */ if (textInfo->flagWord & FONTNUMWAIT) { textInfo->flagWord &= (~FONTNUMWAIT); fontIndex = *str - '0'; if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { if (HandleNewFont(display, fontIndex, textInfo, 0)) { /* Handled font -- go get next character */ continue; } } } /* Inline code for handling normal character case */ if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { register XFontStruct *thisFont; register struct txtLine *thisLine; register int charWidth; /* Determine size of character */ thisFont = &(textInfo->theFonts[textInfo->curFont]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -