To confound and doubly surprise everyone, I started working a textbox a
while ago, had to drop in for a while, and when I picked it up again it
turned out that Micah was busy on the same. So as to not step on toes or
duplicate effort, I'd like to share the general design I was working with.
Like Micah, we realized that this widget would be easier to implement if
pgui operated on sized strings, not null-terminated strings.
I also found that adding a small generic linked list API, similar
to glib's, was very helpful for this.
The text editor's core features are:
- Efficient memory use (O(n) or O(n log n))
- Very fast char insert, delete
- Handles two common worst-cases situations (speed and memory usage)
a. Many newlines (lots of paragraphs)
b. A single huge paragraph
- Widget can be read-only or editable
- Scrollable
- Client may get text, set text, insert string, set cursor position,
set scroll, get virtual height of text area.
- Events were still TBD, but probably add hooks for text insert, delete,
scrolling, and cases where the cursor moves off the top or bottom
of the widget.
Other features (for a later version of the widget) include setting the
font characteristics of a region of text.
This is currently intended only for ASCII text, left-to-right top-to-bottom.
I decided to not implement this widget within the typical grop
context because that seemed to add too much overhead, especially when you
considered cases like editing a 1Mb text file. This is, of course, freely
debateable. From my experience working with a number of GUIs, I've seen that
text widgets tend to simply manage their own drawing in a virtual pane.
After a lot of thought, I adopted a the following data structure. Text
is stored in buffer-gapped blocks. Blocks are organized in a linked list.
Each block contains one or more paragraphs. Paragraphs never span blocks.
All blocks are the same fixed size. If a paragraph grows and cannot fit into
a block, we shed the last paragraph into a new block. If a block contains
just one paragraph and it grows too much to fit in the block, only in this
case do we grow the block's data size.
Buffer-gapping allows for very fast text insert and delete.
Blocks contain paragraphs. Paragraphs contain a linked list of atoms.
Each atom is part of a line of text; atoms may not span lines.
For now, atoms only describe text, though in the future they will also
describe text attributes. Text atoms record the length of text, rendered
width, rendered height, and flags including whether the atom starts on the
left side, ends on the right side, and needs to be drawn. Paragraphs
store the length of the paragraph, rendered height, and whether the paragraph
contains atoms that need to be redraw or rewrapped.
These flags and meta information allow us to quickly render a paragraph. The
nice thing about paragraphs, of course, is that you're gaurenteed that
a paragraph starts at the left side of a text widget. If a paragraph doesn't
need to be re-wrapped, then we know how large it is and can easily render
any part of it.
As you type and edit, paragraphs may be shed to new blocks to free up
space in the buffer gap. There is a periodic idle loop that compacts
blocks with sparse data. Each iteration of the compaction just checks
one more block, so it won't gobble up too much pgui attention.
I hope our ideas can complement one another, and we get a text widget
soon!
-Chuck
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Stuff, things, and much much more.
http://thinkgeek.com/sf
_______________________________________________
Pgui-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/pgui-devel