Rev 44870 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** GraphApp - Cross-Platform Graphics Programming Library.** File: drawtext.c -- cross-platform portable drawing functions.* Platform: Neutral Version: 2.30 Date: 1998/01/01** Version: 1.00 Changes: Original version by Lachlan Patrick.* Version: 1.50 Changes: gprintf now has internal state.* Version: 1.60 Changes: Major bugfixes!* Version: 2.00 Changes: Update to version 2.* Version: 2.01 Changes: Changed unnecessary longs to ints.* Version: 2.20 Changes: Added underlining ability.* Version: 2.30 Changes: Now uses getheight, getdescent.*//* Copyright (C) 1993-1998 Lachlan PatrickThis file is part of GraphApp, a cross-platform C graphics library.GraphApp is free software; you can redistribute it and/or modify itunder the terms of the GNU Library General Public License.GraphApp is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY.See the file COPYLIB.TXT for details.*/#include "internal.h"#include <stdarg.h>#define COMPRESS_WHITESPACE 0static const char *get_next_line(char *line, int width, const char *s){const char *t; char *k;int word_width, line_width;int sp, tab, nl;line_width = 0;for (t=s, k=line; *t!='\0'; line=k, s=t){for (nl=tab=sp=0; (*t!='\0') && isspace(*t) && !nl; t++){#if COMPRESS_WHITESPACEif (*t == '\n') nl++;else if (*t == '\t') tab++;else sp++;#elseif (*t == '\n') nl++;else if (*t == '\t') { /* expand tabs */for (tab=4; tab; tab--)*k++ = ' ';}else*k++ = *t;#endif}s = t;if (nl) { *k++ = '\n'; break; }else if (tab) { *k++ = ' '; *k++ = ' '; }else if (sp) { *k++ = ' '; }/* fetch the next word to draw */for (*k='\0'; (*t!='\0') && !isspace(*t); *k='\0') {if (*t == '-') {*k++ = *t++;*k = '\0';break;}*k++ = *t++;}/* determine where the word should be drawn */while (((word_width = strwidth(current->fnt,line)) > width)&& (k>line)){*(--k) = '\0';--t;}if (word_width > (width - line_width)) {k = line;break;} elseline_width += word_width;}*k = '\0';return (*s == '\0') ? NULL : s;}int textheight(int width, const char *s){int y;char line[256];int height;height = getheight(current->fnt);for(y=0; s; y+=height){s = get_next_line(line, width, s);}return y;}static const char *draw_text_left(char *line, rect r, int line_height,int underline, const char *s){char *k;point p;int width, height;font f;f = current->fnt;for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height){s = get_next_line(line, r.width, s);for (k=line; *k!='\0'; k++)continue;for (--k; (k>=line) && isspace(*k); k--)*k = '\0';drawstr(p, line);if (underline) {width = strwidth(f, line);height = p.y+getheight(f)-getdescent(f)+2;drawline(pt(p.x+1, height), pt(p.x+width-1, height));}}return s;}static const char *draw_text_right(char *line, rect r, int line_height,int underline, const char *s){char *k;int w;point p;int width, height;font f;f = current->fnt;for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height){s = get_next_line(line, r.width, s);for (k=line; *k!='\0'; k++)continue;for (--k; (k>=line) && isspace(*k); k--)*k = '\0';for (k=line; (*k!='\0') && isspace(*k); k++)continue;w = strwidth(current->fnt, k);p.x = r.x+r.width - w;drawstr(p, k);if (underline) {width = strwidth(f, k);height = p.y+getheight(f)-getdescent(f)+2;drawline(pt(p.x+1, height), pt(p.x+width-1, height));}}return s;}static const char *draw_text_centered(char *line, rect r, int line_height,int underline, const char *s){char *k;int w;point p;int width, height;font f;f = current->fnt;for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height){s = get_next_line(line, r.width, s);for (k=line; *k!='\0'; k++)continue;for (--k; (k>=line) && isspace(*k); k--)*k = '\0';for(k=line; (*k!='\0') && isspace(*k); k++)continue;w = strwidth(current->fnt, k);p.x = r.x + (r.width-w)/2;drawstr(p, k);if (underline) {width = strwidth(f, k);height = p.y+getheight(f)-getdescent(f)+2;drawline(pt(p.x+1, height), pt(p.x+width-1, height));}}return s;}static const char *draw_text_justified(char *line, rect r, int line_height,int underline, const char *s){char *j, *k;int w, xw, nl, sc, sw, space_width;point p;int width, height;font f;space_width = strwidth(current->fnt, " ");f = current->fnt;for(p=pt(r.x,r.y); (p.y<=r.y+r.height) && (s); p.y+=line_height){s = get_next_line(line, r.width, s);p.x = r.x;for(j=line; (*j!='\0') && isspace(*j); j++)p.x += space_width;for (sc=0, k=j; *k!='\0'; k++)if (isspace(*k))sc++;for (nl=0, --k; (k>=j) && isspace(*k); k--) {if (*k == '\n')nl++;*k = '\0';sc--;}if ((sc==0) || nl || (! s)) {drawstr(p, j);width = strwidth(f, j);}else {w = strwidth(f, j);sw = space_width + (r.x+r.width-p.x-w)/sc;xw = (r.x+r.width-p.x-w)%sc;for(j=strtok(j," "); j; j=strtok(NULL," ")){drawstr(p, j);p.x += sw + strwidth(f, j);if (xw) {p.x++;xw--;}}width = r.width;}if (underline) {height = p.y+getheight(f)-getdescent(f)+2;drawline(pt(p.x+1, height), pt(p.x+width-1, height));}}return s;}const char *drawtext(rect r, int alignment, const char *s){int h;int nlines;int line_height;int u = 0;rect clip;const char *remains;char line[256];initapp(0,0);if (! s) return (char *) NULL;if (! current->fnt)current->fnt = SystemFont;clip = getcliprect();setcliprect(r);line_height = getheight(current->fnt);if ((alignment & VCenter) == VCenter) {h = textheight(r.width, s);if (h < r.height)r.y += (r.height-h)/2;}else if ((alignment & VJustify) == VJustify) {h = textheight(r.width, s);if (h < r.height) {nlines = h / line_height;if (nlines > 1)line_height += ((r.height-h) / (nlines-1));}}else if ((alignment & AlignBottom) == AlignBottom) {h = textheight(r.width, s);if (h < r.height)r.y += (r.height-h);}u = (alignment & Underline);if ((alignment & Center) == Center)remains = draw_text_centered(line, r, line_height, u, s);else if ((alignment & Justify) == Justify)remains = draw_text_justified(line, r, line_height, u, s);else if ((alignment & AlignRight) == AlignRight)remains = draw_text_right(line, r, line_height, u, s);elseremains = draw_text_left(line, r, line_height, u, s);setcliprect(clip);return remains;}int gprintf(const char *fmt, ...){static point p = {0,0};int count;int line_height;char *s, *t;va_list argptr;char str[256];va_start(argptr, fmt);count = vsprintf(str, fmt, argptr);initapp(0,0);if (! current->fnt)current->fnt = SystemFont;line_height = getheight(current->fnt);for (s=t=str; *s!='\0'; t++) {if (current->p.y != p.y) {/* typewriter ping! */p = current->p;}if (*t == '\n') {/* print everything from s to t and move point down */*t = '\0';drawstr(p, s);current->p.y += line_height;/* go past the substring just printed */s = t+1;}else if (*t == '\0') {/* print final string without newline */p.x += drawstr(p, s);/* go to end of string, signal termination */s = t;}}va_end(argptr);return count;}