📄 fl_text_display.cxx
字号:
//
// "$Id: Fl_Text_Display.cxx,v 1.1.1.1 2003/06/03 22:25:44 agno Exp $"
//
// Copyright 2001-2003 by Bill Spitzak and others.
// Original code Copyright Mark Edel. Permission to distribute under
// the LGPL for the FLTK library granted by Mark Edel.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to "fltk-bugs@fltk.org".
//
#include <stdio.h>
#include <stdlib.h>
#include "flstring.h"
#include <limits.h>
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Window.H>
#undef min
#undef max
// Text area margins. Left & right margins should be at least 3 so that
// there is some room for the overhanging parts of the cursor!
#define TOP_MARGIN 1
#define BOTTOM_MARGIN 1
#define LEFT_MARGIN 3
#define RIGHT_MARGIN 3
#define NO_HINT -1
/* Masks for text drawing methods. These are or'd together to form an
integer which describes what drawing calls to use to draw a string */
#define FILL_MASK 0x100
#define SECONDARY_MASK 0x200
#define PRIMARY_MASK 0x400
#define HIGHLIGHT_MASK 0x800
#define STYLE_LOOKUP_MASK 0xff
/* Maximum displayable line length (how many characters will fit across the
widest window). This amount of memory is temporarily allocated from the
stack in the draw_vline() method for drawing strings */
#define MAX_DISP_LINE_LEN 1000
static int max( int i1, int i2 );
static int min( int i1, int i2 );
static int countlines( const char *string );
// CET - FIXME
#define TMPFONTWIDTH 6
Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
: Fl_Group(X, Y, W, H, l) {
int i;
mMaxsize = 0;
damage_range1_start = damage_range1_end = -1;
damage_range2_start = damage_range2_end = -1;
dragPos = dragType = dragging = 0;
display_insert_position_hint = 0;
color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
box(FL_DOWN_FRAME);
textsize((uchar)FL_NORMAL_SIZE);
textcolor(FL_FOREGROUND_COLOR);
textfont(FL_HELVETICA);
text_area.x = 0;
text_area.y = 0;
text_area.w = 0;
text_area.h = 0;
mVScrollBar = new Fl_Scrollbar(0,0,1,1);
mVScrollBar->callback((Fl_Callback*)v_scrollbar_cb, this);
mHScrollBar = new Fl_Scrollbar(0,0,1,1);
mHScrollBar->callback((Fl_Callback*)h_scrollbar_cb, this);
mHScrollBar->type(FL_HORIZONTAL);
end();
scrollbar_width(16);
scrollbar_align(FL_ALIGN_BOTTOM_RIGHT);
mCursorOn = 0;
mCursorPos = 0;
mCursorOldY = -100;
mCursorToHint = NO_HINT;
mCursorStyle = NORMAL_CURSOR;
mCursorPreferredCol = -1;
mBuffer = 0;
mFirstChar = 0;
mLastChar = 0;
mNBufferLines = 0;
mTopLineNum = mTopLineNumHint = 1;
mAbsTopLineNum = 1;
mNeedAbsTopLineNum = 0;
mHorizOffset = mHorizOffsetHint = 0;
mCursor_color = FL_BLACK;
mFixedFontWidth = TMPFONTWIDTH;// CET - FIXME
mStyleBuffer = 0;
mStyleTable = 0;
mNStyles = 0;
mNVisibleLines = 1;
mLineStarts = new int[mNVisibleLines];
mLineStarts[0] = 0;
for (i=1; i<mNVisibleLines; i++)
mLineStarts[i] = -1;
mSuppressResync = 0;
mNLinesDeleted = 0;
mModifyingTabDistance = 0;
mUnfinishedStyle = 0;
mUnfinishedHighlightCB = 0;
mHighlightCBArg = 0;
mLineNumLeft = mLineNumWidth = 0;
mContinuousWrap = 0;
mWrapMargin = 0;
mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0;
}
/*
** Free a text display and release its associated memory. Note, the text
** BUFFER that the text display displays is a separate entity and is not
** freed, nor are the style buffer or style table.
*/
Fl_Text_Display::~Fl_Text_Display() {
if (mBuffer) mBuffer->remove_modify_callback(buffer_modified_cb, this);
if (mLineStarts) delete[] mLineStarts;
}
/*
** Attach a text buffer to display, replacing the current buffer (if any)
*/
void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) {
/* If the text display is already displaying a buffer, clear it off
of the display and remove our callback from it */
if ( mBuffer != 0 ) {
buffer_modified_cb( 0, 0, mBuffer->length(), 0, 0, this );
mBuffer->remove_modify_callback( buffer_modified_cb, this );
mBuffer->remove_predelete_callback( buffer_predelete_cb, this );
}
/* Add the buffer to the display, and attach a callback to the buffer for
receiving modification information when the buffer contents change */
mBuffer = buf;
mBuffer->add_modify_callback( buffer_modified_cb, this );
mBuffer->add_predelete_callback( buffer_predelete_cb, this );
/* Update the display */
buffer_modified_cb( 0, buf->length(), 0, 0, 0, this );
/* Resize the widget to update the screen... */
resize(x(), y(), w(), h());
}
/*
** Attach (or remove) highlight information in text display and redisplay.
** Highlighting information consists of a style buffer which parallels the
** normal text buffer, but codes font and color information for the display;
** a style table which translates style buffer codes (indexed by buffer
** character - 'A') into fonts and colors; and a callback mechanism for
** as-needed highlighting, triggered by a style buffer entry of
** "unfinishedStyle". Style buffer can trigger additional redisplay during
** a normal buffer modification if the buffer contains a primary Fl_Text_Selection
** (see extendRangeForStyleMods for more information on this protocol).
**
** Style buffers, tables and their associated memory are managed by the caller.
*/
void
Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer,
const Style_Table_Entry *styleTable,
int nStyles, char unfinishedStyle,
Unfinished_Style_Cb unfinishedHighlightCB,
void *cbArg ) {
mStyleBuffer = styleBuffer;
mStyleTable = styleTable;
mNStyles = nStyles;
mUnfinishedStyle = unfinishedStyle;
mUnfinishedHighlightCB = unfinishedHighlightCB;
mHighlightCBArg = cbArg;
mStyleBuffer->canUndo(0);
#if 0
// FIXME: this is in nedit code -- is it needed?
/* Call TextDSetFont to combine font information from style table and
primary font, adjust font-related parameters, and then redisplay */
TextDSetFont(textD, textD->fontStruct);
#endif
damage(FL_DAMAGE_EXPOSE);
}
#if 0
// FIXME: this is in nedit code -- is it needed?
/*
** Change the (non highlight) font
*/
void TextDSetFont(textDisp *textD, XFontStruct *fontStruct) {
Display *display = XtDisplay(textD->w);
int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent;
int width, height, fontWidth;
Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel;
Pixel highlightFGPixel, highlightBGPixel;
XGCValues values;
XFontStruct *styleFont;
/* If font size changes, cursor will be redrawn in a new position */
blankCursorProtrusions(textD);
/* If there is a (syntax highlighting) style table in use, find the new
maximum font height for this text display */
for (i=0; i<textD->nStyles; i++) {
styleFont = textD->styleTable[i].font;
if (styleFont != NULL && styleFont->ascent > maxAscent)
maxAscent = styleFont->ascent;
if (styleFont != NULL && styleFont->descent > maxDescent)
maxDescent = styleFont->descent;
}
textD->ascent = maxAscent;
textD->descent = maxDescent;
/* If all of the current fonts are fixed and match in width, compute */
fontWidth = fontStruct->max_bounds.width;
if (fontWidth != fontStruct->min_bounds.width)
fontWidth = -1;
else {
for (i=0; i<textD->nStyles; i++) {
styleFont = textD->styleTable[i].font;
if (styleFont != NULL && (styleFont->max_bounds.width != fontWidth ||
styleFont->max_bounds.width != styleFont->min_bounds.width))
fontWidth = -1;
}
}
textD->fixedFontWidth = fontWidth;
/* Don't let the height dip below one line, or bad things can happen */
if (textD->height < maxAscent + maxDescent)
textD->height = maxAscent + maxDescent;
/* Change the font. In most cases, this means re-allocating the
affected GCs (they are shared with other widgets, and if the primary
font changes, must be re-allocated to change it). Unfortunately,
this requres recovering all of the colors from the existing GCs */
textD->fontStruct = fontStruct;
XGetGCValues(display, textD->gc, GCForeground|GCBackground, &values);
fgPixel = values.foreground;
bgPixel = values.background;
XGetGCValues(display, textD->selectGC, GCForeground|GCBackground, &values);
selectFGPixel = values.foreground;
selectBGPixel = values.background;
XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values);
highlightFGPixel = values.foreground;
highlightBGPixel = values.background;
releaseGC(textD->w, textD->gc);
releaseGC(textD->w, textD->selectGC);
releaseGC(textD->w, textD->highlightGC);
releaseGC(textD->w, textD->selectBGGC);
releaseGC(textD->w, textD->highlightBGGC);
if (textD->lineNumGC != NULL)
releaseGC(textD->w, textD->lineNumGC);
textD->lineNumGC = NULL;
allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
selectBGPixel, highlightFGPixel, highlightBGPixel);
XSetFont(display, textD->styleGC, fontStruct->fid);
/* Do a full resize to force recalculation of font related parameters */
width = textD->width;
height = textD->height;
textD->width = textD->height = 0;
TextDResize(textD, width, height);
/* Redisplay */
TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
textD->height);
/* Clean up line number area in case spacing has changed */
draw_line_numbers(textD, True);
}
int TextDMinFontWidth(textDisp *textD, Boolean considerStyles) {
int fontWidth = textD->fontStruct->max_bounds.width;
int i;
if (considerStyles) {
for (i = 0; i < textD->nStyles; ++i) {
int thisWidth = (textD->styleTable[i].font)->min_bounds.width;
if (thisWidth < fontWidth) {
fontWidth = thisWidth;
}
}
}
return(fontWidth);
}
int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles) {
int fontWidth = textD->fontStruct->max_bounds.width;
int i;
if (considerStyles) {
for (i = 0; i < textD->nStyles; ++i) {
int thisWidth = (textD->styleTable[i].font)->max_bounds.width;
if (thisWidth > fontWidth) {
fontWidth = thisWidth;
}
}
}
return(fontWidth);
}
#endif
int Fl_Text_Display::longest_vline() {
int longest = 0;
for (int i = 0; i < mNVisibleLines; i++)
longest = max(longest, measure_vline(i));
return longest;
}
/*
** Change the size of the displayed text area
*/
void Fl_Text_Display::resize(int X, int Y, int W, int H) {
const int oldWidth = w();
Fl_Widget::resize(X,Y,W,H);
if (!buffer()) return;
X += Fl::box_dx(box());
Y += Fl::box_dy(box());
W -= Fl::box_dw(box());
H -= Fl::box_dh(box());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -