diff options
| author | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
|---|---|---|
| committer | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
| commit | f9039b2ae21988783feae9b362818e7923e82d14 (patch) | |
| tree | 6d6fe3679d73448758f9794e7d4d4f6b22a4adad /src/fl_draw.cxx | |
| parent | 67e89232f9ba067825a158734a09e0fa21aacbe3 (diff) | |
Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/fl_draw.cxx')
| -rw-r--r-- | src/fl_draw.cxx | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx new file mode 100644 index 000000000..eda4bff29 --- /dev/null +++ b/src/fl_draw.cxx @@ -0,0 +1,175 @@ +// fl_draw.C + +// Implementation of fl_draw(const char*,int,int,int,int,Fl_Align) + +// Used to draw all the labels and text, this routine: + +// Word wraps the labels to fit into their bounding box. +// Breaks them into lines at the newlines. +// Expands all unprintable characters to ^X or \nnn notation +// Aligns them against the inside of the box. + +#include <FL/fl_draw.H> +#include <string.h> + +#define MAXBUF 1024 + +char fl_draw_shortcut; // set by fl_labeltypes.C +static char* underline_at; + +// Copy p to buf, replacing unprintable characters with ^X and \nnn +// Stop at a newline of if MAXBUF characters written to buffer. +// Also word-wrap if width exceeds maxw. +// Returns a pointer to the start of the next line of caharcters. +// Sets n to the number of characters put into the buffer. +// Sets width to the width of the string in the current font. + +static const char* +expand(const char* from, char* buf, double maxw, int& n, double &width, int wrap) { + + char* o = buf; + char* e = buf+(MAXBUF-4); + underline_at = 0; + char* word_end = o; + const char* word_start = from; + double w = 0; + + const char* p = from; + for (;; p++) { + + int c = *p & 255; + + if (!c || c == ' ' || c == '\n') { + // test for word-wrap: + if (word_start < p && wrap) { + double newwidth = w + fl_width(word_end, o-word_end); + if (word_end > buf && newwidth > maxw) { // break before this word + o = word_end; + p = word_start; + break; + } + word_end = o; + w = newwidth; + } + if (!c) break; + else if (c == '\n') {p++; break;} + word_start = p+1; + } + + if (o > e) break; // don't overflow buffer + + if (c == '\t') { + for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' '; + + } else if (c == '&' && fl_draw_shortcut && *(p+1)) { + if (*(p+1) == '&') {p++; *o++ = '&';} + else if (fl_draw_shortcut != 2) underline_at = o; + + } else if (c < ' ' || c == 127) { // ^X + *o++ = '^'; + *o++ = c ^ 0x40; + + } else if (c >= 128 && c < 0xA0) { // \nnn + *o++ = '\\'; + *o++ = (c>>6)+'0'; + *o++ = ((c>>3)&7)+'0'; + *o++ = (c&7)+'0'; + + } else if (c == 0xA0) { // non-breaking space + *o++ = ' '; + + } else { + *o++ = c; + + } + } + + width = w + fl_width(word_end, o-word_end); + *o = 0; + n = o-buf; + return p; +} + +void fl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + Fl_Align align, + void (*callthis)(const char*,int,int,int) +) { + if (!str || !*str) return; + + // clip: + if (w && h && !fl_not_clipped(x, y, w, h)) return; + if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h); + + const char* p; + const char* e; + char buf[MAXBUF]; + int buflen; + + // count how many lines and put the last one into the buffer: + int lines; + double width; + for (p=str,lines=0; ;) { + e = expand(p, buf, w, buflen, width, align&FL_ALIGN_WRAP); + lines++; + if (!*e) break; + p = e; + } + + // figure out vertical position of the first line: + int ypos; + int height = fl_height(); + if (align & FL_ALIGN_BOTTOM) ypos = y+h-(lines-1)*height; + else if (align & FL_ALIGN_TOP) ypos = y+height; + else ypos = y+(h-lines*height)/2+height; + + // now draw all the lines: + int desc = fl_descent(); + for (p=str; ; ypos += height) { + if (lines>1) e = expand(p, buf, w, buflen, width, align&FL_ALIGN_WRAP); + + int xpos; + if (align & FL_ALIGN_LEFT) xpos = x; + else if (align & FL_ALIGN_RIGHT) xpos = x+w-int(width+.5); + else xpos = x+int((w-width)/2); + + callthis(buf,buflen,xpos,ypos-desc); + + if (underline_at) + callthis("_",1,xpos+int(fl_width(buf,underline_at-buf)),ypos-desc); + + if (!*e) break; + p = e; + } + + if (align & FL_ALIGN_CLIP) fl_pop_clip(); +} + +void fl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + Fl_Align align) { + fl_draw(str, x, y, w, h, align, fl_draw); +} + +void fl_measure(const char* str, int& w, int& h) { + h = fl_height(); + if (!str || !*str) {w = 0; return;} + const char* p; + const char* e; + char buf[MAXBUF]; + int buflen; + int lines; + double width; + int W = 0; + for (p=str,lines=0; ;) { + e = expand(p, buf, w, buflen, width, w!=0); + if (int(width) > W) W = int(width); + lines++; + if (!*e) break; + p = e; + } + w = W; + h = lines*h; +} |
