summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2014-05-21 06:56:59 +0000
committerGreg Ercolano <erco@seriss.com>2014-05-21 06:56:59 +0000
commit46521bf437f712234904a4295cb75ba15d168b5f (patch)
treea89d0c692e005f4bc6c688374ab4333efa79d0ec
parentcb0f80cde7ced7ba1d98c8d1e3c713331ab5b5bf (diff)
Implements STR #2621: Add line numbers to Fl_Text_Display.
Applied LZA's patch and included some mods to address TODO items and ABI issues. Also update CREDITS with LZA and a few other notably absent names. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10152 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CREDITS3
-rw-r--r--FL/Fl_Text_Display.H80
-rw-r--r--src/Fl_Text_Display.cxx323
-rw-r--r--test/editor.cxx16
4 files changed, 350 insertions, 72 deletions
diff --git a/CREDITS b/CREDITS
index 653593926..34e90317e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -41,6 +41,7 @@ OTHER CONTRIBUTORS
The following people have contributed fixes or enhancements
for FLTK:
+ Laszlo Z. Antal (LZA)
Teun Burgers
Paul Chambers
Stephen Davies
@@ -51,11 +52,13 @@ OTHER CONTRIBUTORS
Duncan Gibson
Mikael Hultgren
Stuart Levy
+ Jean-Marc Lienher (OksiD)
Howard Lightstone
Mike Lindner
Alexander Mai
Alexander Rabi
James Roth
+ Ivan Nieto (Mr.Satan)
Jamie Snape
Andrea Suatoni
Michael Surette
diff --git a/FL/Fl_Text_Display.H b/FL/Fl_Text_Display.H
index 9acae008b..f1ae90ed8 100644
--- a/FL/Fl_Text_Display.H
+++ b/FL/Fl_Text_Display.H
@@ -33,10 +33,51 @@
/**
\brief Rich text display widget.
- This is the FLTK text display widget. It allows the user to view multiple lines
- of text and supports highlighting and scrolling. The buffer that is displayed
- in the widget is managed by the Fl_Text_Buffer class. A single Text Buffer
- can be displayed by multiple Text Displays.
+ This is the FLTK text display widget. It allows the user to view
+ multiple lines of text and supports highlighting, word wrap, mixes
+ of font faces and colors, line numbers and scrolling. The buffer
+ that is displayed in the widget is managed by the Fl_Text_Buffer
+ class. A single Text Buffer can be displayed by multiple Text
+ Displays.
+
+ \image html editor.png "Fl_Text_Display widget"
+ \image latex editor.png "Fl_Text_Display widget" width=6cm
+ <BR><BR>
+ \image html editor-linenumbers.png "Fl_Text_Display widget with line numbers enabled"
+ \image latex editor-linenumbers.png "Fl_Text_Display widget with line numbers enabled" width=6cm
+
+ \b Example \b Use
+ \code
+ #include <FL/FL_Text_Display.H>
+ ..
+ int main() {
+ ..
+ Fl_Text_Buffer *buff = new Fl_Text_Buffer();
+ Fl_Text_Display *disp = new Fl_Text_Display(10, 10, 640, 480);
+ disp->buffer(buff); // attach text buffer to display widget
+ buff->text("line one\nline two"); // add some text to buffer
+ ..
+ }
+ \endcode
+
+ \b Features
+
+ - Word wrap: wrap_mode(), wrapped_column(), wrapped_row()
+ - Font control: textfont(), textsize(), textcolor()
+ - Font styling: highlight_data()
+ - Cursor: cursor_style(), show_cursor(), hide_cursor(), cursor_color()
+ - Line numbers: linenumber_width(), linenumber_font(),
+ linenumber_size(), linenumber_fgcolor(), linenumber_bgcolor(),
+ linenumber_align(), linenumber_format()
+
+ Note that other features may be available via Fl_Text_Editor
+ and Fl_Text_Buffer classes.
+
+ \note Line numbers were added in 1.3.3. To avoid breaking ABI,
+ many of its options are read only. To adjust these features
+ in 1.3.x, you must build FLTK with FLTK_ABI_VERSION set to 10303
+ or higher.
+
*/
class FL_EXPORT Fl_Text_Display: public Fl_Group {
@@ -290,6 +331,21 @@ public:
*/
double col_to_x(double col) const;
+ void linenumber_width(int width);
+ int linenumber_width() const;
+ void linenumber_font(Fl_Font val);
+ Fl_Font linenumber_font() const;
+ void linenumber_size(Fl_Fontsize val);
+ Fl_Fontsize linenumber_size() const;
+ void linenumber_fgcolor(Fl_Color val);
+ Fl_Color linenumber_fgcolor() const;
+ void linenumber_bgcolor(Fl_Color val);
+ Fl_Color linenumber_bgcolor() const;
+ void linenumber_align(Fl_Align val);
+ Fl_Align linenumber_align() const;
+ void linenumber_format(const char* val);
+ const char* linenumber_format() const;
+
protected:
// Most (all?) of this stuff should only be called from resize() or
// draw().
@@ -457,12 +513,18 @@ protected:
Fl_Fontsize textsize_;
Fl_Color textcolor_;
- // The following are not presently used from the original NEdit code,
- // but are being put here so that future versions of Fl_Text_Display
- // can implement line numbers without breaking binary compatibility.
-
- /* Line number margin and width */
+ // Line number margin and width
int mLineNumLeft, mLineNumWidth;
+
+ // Line number font/colors
+#if FLTK_ABI_VERSION >= 10303
+ Fl_Font linenumber_font_;
+ Fl_Fontsize linenumber_size_;
+ Fl_Color linenumber_fgcolor_;
+ Fl_Color linenumber_bgcolor_;
+ Fl_Align linenumber_align_;
+ const char* linenumber_format_;
+#endif
};
#endif
diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx
index 0b5d75c3f..564611ad2 100644
--- a/src/Fl_Text_Display.cxx
+++ b/src/Fl_Text_Display.cxx
@@ -17,7 +17,7 @@
//
// TODO: rendering of the "optional hyphen"
-// TODO: make line numbering work again
+// TODO: font background color control via style buffer
#include <stdio.h>
#include <stdlib.h>
@@ -152,6 +152,14 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
mContinuousWrap = 0;
mWrapMarginPix = 0;
mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0;
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_font_ = FL_HELVETICA;
+ linenumber_size_ = FL_NORMAL_SIZE;
+ linenumber_fgcolor_ = FL_INACTIVE_COLOR;
+ linenumber_bgcolor_ = 53; // ~90% gray
+ linenumber_align_ = FL_ALIGN_RIGHT;
+ linenumber_format_ = "%d";
+#endif
}
@@ -175,6 +183,171 @@ Fl_Text_Display::~Fl_Text_Display() {
}
+/**
+ Set width of screen area for line numbers.
+ Use to also enable/disable line numbers.
+ A value of 0 disables line numbering, values >0 enables them.
+ \param width The new width of the area for line numbers to appear, in pixels.
+ 0 disables line numbers (default)
+*/
+void Fl_Text_Display::linenumber_width(int width) {
+ if (width < 0) return;
+ mLineNumWidth = width;
+ resize(x(), y(), w(), h()); // triggers code to recalculate line#s
+}
+
+/**
+ Return the screen area width provided for line numbers.
+*/
+int Fl_Text_Display::linenumber_width() const {
+ return mLineNumWidth;
+}
+
+/**
+ Set the font used for line numbers (if enabled).
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_font(Fl_Font val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_font_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Return the font used for line numbers (if enabled).
+*/
+Fl_Font Fl_Text_Display::linenumber_font() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_font_;
+#else
+ return FL_HELVETICA;
+#endif
+}
+
+/**
+ Set the font size used for line numbers (if enabled).
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_size(Fl_Fontsize val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_size_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Return the font size used for line numbers (if enabled).
+*/
+Fl_Fontsize Fl_Text_Display::linenumber_size() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_size_;
+#else
+ return FL_NORMAL_SIZE;
+#endif
+}
+
+/**
+ Set the foreground color used for line numbers (if enabled).
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_fgcolor(Fl_Color val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_fgcolor_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Return the foreground color used for line numbers (if enabled).
+*/
+Fl_Color Fl_Text_Display::linenumber_fgcolor() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_fgcolor_;
+#else
+ return FL_INACTIVE_COLOR;
+#endif
+}
+
+/**
+ Set the background color used for line numbers (if enabled).
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_bgcolor(Fl_Color val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_bgcolor_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Returns the background color used for line numbers (if enabled).
+*/
+Fl_Color Fl_Text_Display::linenumber_bgcolor() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_bgcolor_;
+#else
+ return 53; // hard coded ~90% gray
+#endif
+}
+
+/**
+ Set alignment for line numbers (if enabled).
+ Valid values are FL_ALIGN_LEFT, FL_ALIGN_CENTER or FL_ALIGN_RIGHT.
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_align(Fl_Align val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_align_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Returns the alignment used for line numbers (if enabled).
+*/
+Fl_Align Fl_Text_Display::linenumber_align() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_align_;
+#else
+ return FL_ALIGN_RIGHT;
+#endif
+}
+
+/**
+ Sets the printf() style format string used for line numbers.
+ Default is "%d" for normal unpadded decimal integers. Example values:
+
+ - "%d" -- For normal line numbers without padding (Default)
+ - "%03d" -- For 000 padding
+ - "%x" -- For hexadecimal line numbers
+ - "%o" -- For octal line numbers
+
+ \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher)
+*/
+void Fl_Text_Display::linenumber_format(const char* val) {
+#if FLTK_ABI_VERSION >= 10303
+ linenumber_format_ = val;
+#else
+ // do nothing
+#endif
+}
+
+/**
+ Returns the line number printf() format string.
+*/
+const char* Fl_Text_Display::linenumber_format() const {
+#if FLTK_ABI_VERSION >= 10303
+ return linenumber_format_;
+#else
+ return "%d";
+#endif
+}
/**
Attach a text buffer to display, replacing the current buffer (if any)
@@ -406,6 +579,12 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) {
}
}
+ // add linenum width to the text area - LZA / STR#2621
+ if (mLineNumWidth > 0) {
+ text_area.x += mLineNumWidth;
+ text_area.w -= mLineNumWidth;
+ }
+
// user request to change viewport
if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset)
scroll_(mTopLineNumHint, mHorizOffsetHint);
@@ -465,10 +644,6 @@ void Fl_Text_Display::draw_text( int left, int top, int width, int height ) {
for ( line = firstLine; line <= lastLine; line++ )
draw_vline( line, left, left + width, 0, INT_MAX );
- /* draw the line numbers if exposed area includes them */
- if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth)
- draw_line_numbers(false);
-
fl_pop_clip();
}
@@ -700,7 +875,7 @@ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) {
mNBufferLines = 0;
mFirstChar = 0;
mTopLineNum = 1;
- mAbsTopLineNum = 0;
+ mAbsTopLineNum = 1; // changed from 0 to 1 -- LZA / STR#2621
}
resize(x(), y(), w(), h());
@@ -1514,8 +1689,10 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
// CET - FIXME if ( origCursorPos >= startDispPos &&
// ( origCursorPos <= endDispPos || endDispPos == buf->length() ) )
}
-
- if (linesInserted > 1) textD->draw_line_numbers(false);
+ if (linesInserted > 1) {
+ // textD->draw_line_numbers(false); // can't do this b/c not called from virtual draw();
+ textD->damage(::FL_DAMAGE_EXPOSE);
+ }
} else {
endDispPos = buf->next_char(textD->mLastChar);
// CET - FIXME if ( origCursorPos >= pos )
@@ -1524,7 +1701,11 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
have changed. If only one line is altered, line numbers cannot
be affected (the insertion or removal of a line break always
results in at least two lines being redrawn). */
- textD->draw_line_numbers(false);
+
+ // Call draw_line_numbers() here to ensure line# is drawn
+ // when hitting enter for new line -- LZA / STR #2621
+ //textD->draw_line_numbers(true); // no, can't call this here, not in draw() context -- ERCO / STR#2621
+ //textD->damage(::FL_DAMAGE_EXPOSE);
}
IS_UTF8_ALIGNED2(buf, startDispPos)
IS_UTF8_ALIGNED2(buf, endDispPos)
@@ -1543,6 +1724,7 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted,
}
+/* Line Numbering Methods */
/**
\brief Line numbering stuff, currently unused.
@@ -2645,63 +2827,74 @@ void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) {
/**
\brief Refresh the line number area.
-
- If clearAll is False, writes only over the character cell areas. Setting
- clearAll to True will clear out any stray marks outside of the character cell
- area, which might have been left from before a resize or font change.
-
- This function is not used.
+ \param clearAll -- (currently unused) If False, only draws the line number text,
+ does not clear the area behind it. If True, clears the area
+ and redraws the text. Use False to avoid a 'flash' for
+ single buffered windows.
*/
+
+// This draw_line_numbers() method based on patch from
+// http://www.mail-archive.com/fltk-dev@easysw.com/msg06376.html
+// altered to support line numbers right alignment. -LZA / STR #2621
+//
void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) {
-#if 0
- int y, line, visLine, nCols, lineStart;
- char lineNumString[12];
- int lineHeight = mMaxsize ? mMaxsize : textsize_;
- int charWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width;
-
- /* Don't draw if mLineNumWidth == 0 (line numbers are hidden), or widget is
- not yet realized */
- if (mLineNumWidth == 0 || visible_r())
+ int Y, line, visLine, lineStart;
+ char lineNumString[16];
+ int lineHeight = mMaxsize;
+
+ // Don't draw if lineNumWidth == 0 (line numbers are hidden),
+ // or widget is not yet realized
+ if (mLineNumWidth <= 0 || !visible_r())
return;
- /* GC is allocated on demand, since not everyone will use line numbering */
- if (textD->lineNumGC == NULL) {
- XGCValues values;
- values.foreground = textD->lineNumFGPixel;
- values.background = textD->bgPixel;
- values.font = textD->fontStruct->fid;
- textD->lineNumGC = XtGetGC(textD->w,
- GCFont| GCForeground | GCBackground, &values);
- }
-
- /* Erase the previous contents of the line number area, if requested */
- if (clearAll)
- XClearArea(XtDisplay(textD->w), XtWindow(textD->w), textD->lineNumLeft,
- textD->top, textD->lineNumWidth, textD->height, False);
-
- /* Draw the line numbers, aligned to the text */
- nCols = min(11, textD->lineNumWidth / charWidth);
- y = textD->top;
- line = getAbsTopLineNum(textD);
- for (visLine=0; visLine < textD->nVisibleLines; visLine++) {
- lineStart = textD->lineStarts[visLine];
- if (lineStart != -1 && (lineStart==0 ||
- BufGetCharacter(textD->buffer, lineStart-1)=='\n')) {
- sprintf(lineNumString, "%*d", nCols, line);
- XDrawImageString(XtDisplay(textD->w), XtWindow(textD->w),
- textD->lineNumGC, textD->lineNumLeft, y + textD->ascent,
- lineNumString, strlen(lineNumString));
- line++;
- } else {
- XClearArea(XtDisplay(textD->w), XtWindow(textD->w),
- textD->lineNumLeft, y, textD->lineNumWidth,
- textD->ascent + textD->descent, False);
- if (visLine == 0)
- line++;
+ // Make sure we reset clipping range for line number's GC;
+ // it may be shared (e.g. if line numbers and text have same color)
+ // and therefore clipping ranges may be invalid.
+ int xoff = Fl::box_dx(box());
+ int hscroll_h = mHScrollBar->visible() ? mHScrollBar->h() : 0;
+ fl_push_clip(x() + xoff,
+ y() + Fl::box_dy(box()),
+ mLineNumWidth - xoff,
+ h() - Fl::box_dh(box()) - hscroll_h);
+ {
+ // Set background color for line number area -- LZA / STR# 2621
+ // Erase background
+ fl_color(linenumber_bgcolor());
+ fl_rectf(x(), y(), mLineNumWidth, h());
+
+ // Draw separator line
+ //fl_color(180,180,180);
+ //fl_line(x()+mLineNumWidth-1, y(), x()+mLineNumWidth-1, y()+h());
+
+ // Draw line number text
+ fl_font(linenumber_font(), linenumber_size());
+
+ Y = y();
+ line = get_absolute_top_line_number();
+
+ int last_y = y();
+
+ // set font color for line numbers
+ fl_color(linenumber_fgcolor());
+ for (visLine=0; visLine < mNVisibleLines; visLine++) {
+ lineStart = mLineStarts[visLine];
+ if (lineStart != -1 && (lineStart==0 || buffer()->char_at(lineStart-1)=='\n')) {
+ sprintf(lineNumString, linenumber_format(), line);
+ int xx = x() + xoff + 3,
+ yy = Y + 3,
+ ww = mLineNumWidth - xoff - (3*2),
+ hh = lineHeight;
+ fl_draw(lineNumString, xx, yy, ww, hh, linenumber_align(), 0, 0);
+ //DEBUG fl_rect(xx, yy, ww, hh);
+ last_y = Y;
+ line++;
+ } else {
+ if (visLine == 0) line++;
+ }
+ Y += lineHeight;
}
- y += lineHeight;
- }
-#endif
+ }
+ fl_pop_clip();
}
static int max( int i1, int i2 ) {
@@ -3416,8 +3609,7 @@ void Fl_Text_Display::draw(void) {
fl_rectf(mVScrollBar->x(), mHScrollBar->y(),
mVScrollBar->w(), mHScrollBar->h(),
FL_GRAY);
-
- // blank the previous cursor protrusions
+ //draw_line_numbers(true); // commented out STR# 2621 / LZA
}
else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) {
// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY);
@@ -3494,6 +3686,11 @@ void Fl_Text_Display::draw(void) {
//printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y);
fl_pop_clip();
}
+
+ // Important to do this at end of this method, otherwise line numbers
+ // will not scroll with the text edit area
+ draw_line_numbers(true);
+
fl_pop_clip();
}
diff --git a/test/editor.cxx b/test/editor.cxx
index 1c9db095f..54245ab42 100644
--- a/test/editor.cxx
+++ b/test/editor.cxx
@@ -515,6 +515,19 @@ void delete_cb(Fl_Widget*, void*) {
textbuf->remove_selection();
}
+void linenumbers_cb(Fl_Widget *w, void* v) {
+ EditorWindow* e = (EditorWindow*)v;
+ Fl_Menu_Bar* m = (Fl_Menu_Bar*)w;
+ const Fl_Menu_Item* i = m->mvalue();
+ if ( i->value() ) {
+ e->editor->linenumber_width(50); // enable
+ e->editor->linenumber_size(e->editor->textsize());
+ } else {
+ e->editor->linenumber_width(0); // disable
+ }
+ e->redraw();
+}
+
void find_cb(Fl_Widget* w, void* v) {
EditorWindow* e = (EditorWindow*)v;
const char *val;
@@ -751,6 +764,9 @@ Fl_Menu_Item menuitems[] = {
{ "&Copy", FL_COMMAND + 'c', (Fl_Callback *)copy_cb },
{ "&Paste", FL_COMMAND + 'v', (Fl_Callback *)paste_cb },
{ "&Delete", 0, (Fl_Callback *)delete_cb },
+ { "Preferences", 0, 0, 0, FL_SUBMENU },
+ { "Line Numbers", FL_COMMAND + 'l', (Fl_Callback *)linenumbers_cb, 0, FL_MENU_TOGGLE },
+ { 0 },
{ 0 },
{ "&Search", 0, 0, 0, FL_SUBMENU },