sprintf(): Fix a serious bug; snprintf(): New function.
[bertos.git] / mware / text_format.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 1999 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  * \author Stefano Fedrigo <aleph@develer.com>
13  *
14  * \brief printf-family routines for text output
15  */
16
17 /*#*
18  *#* $Log$
19  *#* Revision 1.6  2004/09/14 20:59:04  bernie
20  *#* text_xprintf(): Support all styles; Pixel-wise text centering.
21  *#*
22  *#* Revision 1.5  2004/08/25 14:12:09  rasky
23  *#* Aggiornato il comment block dei log RCS
24  *#*
25  *#* Revision 1.4  2004/08/05 18:46:44  bernie
26  *#* Documentation improvements.
27  *#*
28  *#* Revision 1.3  2004/08/03 15:57:18  aleph
29  *#* Add include to fix warning for vsprintf()
30  *#*
31  *#* Revision 1.2  2004/06/03 11:27:09  bernie
32  *#* Add dual-license information.
33  *#*
34  *#* Revision 1.1  2004/05/23 15:43:16  bernie
35  *#* Import mware modules.
36  *#*
37  *#* Revision 1.2  2004/03/26 18:50:50  bernie
38  *#* Move _PROGMEM stuff to compiler.h
39  *#*
40  *#* Revision 1.1  2004/03/19 16:52:28  bernie
41  *#* Move printf() like functions from text.c to text_format.c and add PROGMEM versions.
42  *#*
43  *#*/
44
45 #include "text.h"
46 #include "formatwr.h" /* _formatted_write() */
47 #include "font.h"
48 #include "gfx.h"
49 #include <stdio.h> /* vsprintf() */
50 #include <stdarg.h>
51 #include <string.h> /* strlen() */
52
53 /*!
54  * Render string \a str in Bitmap \a bm at current cursor position
55  *
56  * \note Text formatting functions are also available with an _P suffix
57  *       accepting the source string from program memory.  This feature
58  *       is only available (and useful) on Harvard microprocessors such
59  *       as the AVR.
60  *
61  * \see text_putchar()
62  */
63 int PGM_FUNC(text_puts)(const char * PGM_ATTR str, struct Bitmap *bm)
64 {
65         char c;
66
67         while ((c = PGM_READ_CHAR(str++)))
68                 text_putchar(c, bm);
69
70         return 0;
71 }
72
73
74 /*!
75  * vprintf()-like formatter to render text in a Bitmap.
76  *
77  * Perform vprintf()-like formatting on the \a fmt format string using the
78  * variable-argument list \a ap.
79  * Render the resulting string in Bitmap \a bm starting at the current
80  * cursor position.
81  *
82  * \see text_puts() text_putchar() text_printf()
83  */
84 int PGM_FUNC(text_vprintf)(struct Bitmap *bm, const char * PGM_ATTR fmt, va_list ap)
85 {
86         return PGM_FUNC(_formatted_write)(fmt, (void (*)(char, void *))text_putchar, bm, ap);
87 }
88
89 /*!
90  * printf()-like formatter to render text in a Bitmap.
91  *
92  * Perform printf()-like formatting on the \a fmt format string.
93  * Render the resulting string in Bitmap \a bm starting at the
94  * current cursor position.
95  *
96  * \see text_puts() text_putchar() text_vprintf()
97  */
98 int PGM_FUNC(text_printf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
99 {
100         int len;
101
102         va_list ap;
103         va_start(ap, fmt);
104         len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
105         va_end(ap);
106
107         return len;
108 }
109
110
111 /*!
112  * Render the result of printf()-like formatting in a specified position
113  * of a Bitmap.
114  *
115  * \param bm Bitmap where to render the text
116  * \param row   Starting row in character units (zero based)
117  * \param col   Starting column in character units (zero based)
118  * \param style Formatting style to use.  In addition to any STYLEF_
119  *        flag, it can be TEXT_NORMAL, TEXT_FILL, TEXT_INVERT or
120  *        TEXT_RIGHT, or a combination of these flags ORed together.
121  * \param fmt  String possibly containing printf() formatting commands.
122  *
123  * \see text_puts() text_putchar() text_printf() text_vprintf()
124  * \see text_moveto() text_style()
125  */
126 int PGM_FUNC(text_xprintf)(struct Bitmap *bm,
127                 uint8_t row, uint8_t col, uint16_t style, const char * PGM_ATTR fmt, ...)
128 {
129         int len;
130         uint8_t oldstyle = 0;
131         va_list ap;
132
133         va_start(ap, fmt);
134
135         text_moveto(bm, row, col);
136
137         if (style & STYLEF_MASK)
138                 oldstyle = text_style(style, STYLEF_MASK);
139
140         if (style & (TEXT_CENTER | TEXT_RIGHT))
141         {
142                 uint8_t pad = bm->width - PGM_FUNC(vsprintf)(NULL, fmt, ap) * FONT_WIDTH;
143
144                 if (style & TEXT_CENTER)
145                         pad /= 2;
146
147                 if (style & TEXT_FILL)
148                         gfx_RectFillC(bm, 0, row * FONT_HEIGHT, pad, (row + 1) * FONT_HEIGHT,
149                                 (style & STYLEF_INVERT) ? 0xFF : 0x00);
150
151                 text_setcoord(bm, pad, row * FONT_HEIGHT);
152         }
153
154         len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
155         va_end(ap);
156
157         if (style & TEXT_FILL)
158                 gfx_RectFillC(bm, bm->penX, row * FONT_HEIGHT, bm->width, (row + 1) * FONT_HEIGHT,
159                         (style & STYLEF_INVERT) ? 0xFF : 0x00);
160
161         /* Restore old style */
162         if (style & STYLEF_MASK)
163                 text_style(oldstyle, STYLEF_MASK);
164
165         return len;
166 }
167