Tscope5
textio.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __ ______
4 // / /_______________ ____ ___ / ____/
5 // / __/ ___/ ___/ __ \/ __ \/ _ \ /___ )
6 // / /_(__ ) /__/ /_/ / /_/ / __/ ____/ /
7 // \__/____/\___/\____/ .___/\___/ /_____/
8 // /_/
9 //
10 /// \file textio.c
11 /// Definitions of text input/output functions
12 /// \example textio01.c
13 /// \example textio02.c
14 /// \example textio03.c
15 /// \example textio04.c
16 /// \example textio05.c
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 
20 #include "../include/tscope5/textio.h"
21 #include "../include/tscope5/display.h"
22 #include "../include/tscope5/graphics.h"
23 #include "../include/tscope5/textio_internal.h"
24 #include "../include/tscope5/system_internal.h"
25 #include "../include/tscope5/keyboard_internal.h"
26 #include "../include/tscope5/graphics_internal.h"
27 
28 
29 #include <allegro5/allegro_font.h>
30 #include <allegro5/allegro_ttf.h>
31 
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// @name Text input/output functions
35 /// The text input-output functions all take the smallest possible number of
36 /// parameters to put something on the screen:
37 /// two coordinates and a format string.
38 ///
39 /// The vertical coordinates are interpreted differently by
40 /// the two coordinate systems.
41 /// - When using the Cartesian coordinate system,
42 /// text is vertically centered around the y coordinate.
43 /// - When using the Display coordinate system,
44 /// the y coordinate corresponds to the top of the text
45 /// (like in other libraries).
46 ///
47 /// The format string is the same as the standard C
48 /// printf and scanf function families.
49 ///
50 /// Both standard C strings and Unicode strings can be used.
51 ///
52 /// Drawing parameters are set with the graphics parameter functions.
53 //@{
54 ////////////////////////////////////////////////////////////////////////////////
55 
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Write text to the active bitmap.
59 ///
60 /// \param x Horizontal position of the text.
61 /// \param y Vertical position of the text.
62 /// \param format Printf style format string.
63 ///
64 /// \return Length of the string on the display (in pixels).
65 ////////////////////////////////////////////////////////////////////////////////
66 double ts5_printf(double x, double y, const char *format, ...)
67 {
68  ts5_check_textio("ts5_printf");
69  ts5_log(TS5_LOGLEVEL_5, "ts5_printf(%f,%f,...)\n", x, y);
70 
71  if (_ts5_status.graphics.coordinate_scale
72  == TS5_RELATIVE_COORDINATES) {
75  }
76 
77  if (_ts5_status.graphics.coordinate_system
78  == TS5_CARTESIAN_COORDINATES) {
81  + _ts5_status.graphics.font_size / 2.0);
82  }
83 
84  TS5_USTR *buf;
85  va_list ap;
86  double width;
87 
88  va_start(ap, format);
89  buf = al_ustr_new("");
90  al_ustr_vappendf(buf, format, ap);
91  va_end(ap);
92 
93  al_draw_ustr(_ts5_status.graphics.font,
94  _ts5_status.graphics.foreground_color,
95  x, y, _ts5_status.graphics.text_alignment, buf);
96 
97  width = al_get_ustr_width(_ts5_status.graphics.font, buf);
98  al_ustr_free(buf);
99 
100  if (_ts5_status.graphics.coordinate_scale
101  == TS5_RELATIVE_COORDINATES) {
102  width/=_ts5_status.graphics.target_width;
103  }
104 
105  return width;
106 }
107 
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Write justified text to the active bitmap.
111 ///
112 /// \param x1 Horizontal start position of the text.
113 /// \param x2 Horizontal end position of the text.
114 /// \param y Vertical position of the text.
115 /// \param diff Maximum amount of space. If the amount of space in a line
116 /// of text is greater than the diff value, left justified text will be written.
117 /// \param format Printf style format string.
118 ////////////////////////////////////////////////////////////////////////////////
119 void ts5_printf_justify(double x1, double x2, double y, const double diff,
120  const char *format, ...)
121 {
122  ts5_check_textio("ts5_printf_justify");
123  ts5_log(TS5_LOGLEVEL_5, "ts5_printf_justify(%f,%f,%f,%f,...)\n",
124  x1, x2, y, diff);
125 
126  if (_ts5_status.graphics.coordinate_scale
127  == TS5_RELATIVE_COORDINATES) {
131  }
132 
133  if (_ts5_status.graphics.coordinate_system
134  == TS5_CARTESIAN_COORDINATES) {
138  + _ts5_status.graphics.font_size / 2.0);
139  }
140 
141  TS5_USTR *buf;
142  va_list ap;
143 
144  va_start(ap, format);
145  buf = al_ustr_new("");
146  al_ustr_vappendf(buf, format, ap);
147  va_end(ap);
148 
149  al_draw_justified_ustr(_ts5_status.graphics.font,
150  _ts5_status.graphics.foreground_color,
151  x1, x2, y, diff,
152  _ts5_status.graphics.text_alignment, buf);
153 }
154 
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Write UTF-8 encoded text to the active bitmap.
158 ///
159 /// \param x Horizontal position of the text.
160 /// \param y Vertical position of the text.
161 /// \param ustr Unicode string.
162 ///
163 /// \return Length of the string on the display (in pixels).
164 ////////////////////////////////////////////////////////////////////////////////
165 double ts5_printf_ustr(double x, double y, const TS5_USTR *ustr)
166 {
167  ts5_check_textio("ts5_printf_ustr");
168  ts5_log(TS5_LOGLEVEL_5, "ts5_printf_ustr(%f,%f,...)\n", x, y);
169 
170  if (_ts5_status.graphics.coordinate_scale
171  == TS5_RELATIVE_COORDINATES) {
174  }
175 
176  if (_ts5_status.graphics.coordinate_system
177  == TS5_CARTESIAN_COORDINATES) {
180  + _ts5_status.graphics.font_size / 2.0);
181  }
182 
183  double width;
184  al_draw_ustr(_ts5_status.graphics.font,
185  _ts5_status.graphics.foreground_color,
186  x, y, _ts5_status.graphics.text_alignment, ustr);
187 
188  width = al_get_ustr_width(_ts5_status.graphics.font, ustr);
189 
190  if (_ts5_status.graphics.coordinate_scale
191  == TS5_RELATIVE_COORDINATES) {
192  width/=_ts5_status.graphics.target_width;
193  }
194 
195  return width;
196 }
197 
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Write justified UTF-8 encoded text to the active bitmap.
201 ///
202 /// \param x1 Horizontal start position of the text.
203 /// \param x2 Horizontal end position of the text.
204 /// \param y Vertical position of the text.
205 /// \param diff Maximum amount of space. If the amount of space in a line
206 /// of text is greater than the diff value, left justified text will be written.
207 /// \param ustr Unicode string.
208 ////////////////////////////////////////////////////////////////////////////////
209 void ts5_printf_justify_ustr(double x1, double x2, double y, const double diff,
210  const TS5_USTR *ustr)
211 {
212  ts5_check_textio("ts5_printf_justify_ustr");
213  ts5_log(TS5_LOGLEVEL_5, "ts5_printf_justify_ustr(%f,%f,%f,%f,...)\n",
214  x1, x2, y, diff);
215 
216  if (_ts5_status.graphics.coordinate_scale
217  == TS5_RELATIVE_COORDINATES) {
221  }
222 
223  if (_ts5_status.graphics.coordinate_system
224  == TS5_CARTESIAN_COORDINATES) {
228  + _ts5_status.graphics.font_size / 2.0);
229  }
230 
231  al_draw_justified_ustr(_ts5_status.graphics.font,
232  _ts5_status.graphics.foreground_color,
233  x1, x2, y, diff,
234  _ts5_status.graphics.text_alignment, ustr);
235 }
236 
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Read text from the keyboard.
240 ///
241 /// \param x Horizontal position where the input will be echoed.
242 /// \param y Vertical position where the input will be echoed.
243 /// \param format Printf style format string.
244 ///
245 /// \return The number of arguments that were processed.
246 ////////////////////////////////////////////////////////////////////////////////
247 int ts5_scanf(double x, double y, const char *format, ...)
248 {
249  ts5_check_textio("ts5_scanf");
250  ts5_check_keyboard("ts5_scanf");
251  ts5_log(TS5_LOGLEVEL_5, "ts5_scanf(%f,%f,...)\n", x, y);
252 
253  char str[TS5_MAX_CHAR];
254  int done = 0, pos = 0;
255  int ascii;
256  TS5_COLOR fg = _ts5_status.graphics.foreground_color;
257  TS5_COLOR bg = _ts5_status.graphics.background_color;
258 
259  ALLEGRO_EVENT_QUEUE *event_queue;
260  event_queue = al_create_event_queue();
261 
262  if (!event_queue) {
263  ts5_fatal("ts5_scanf: could not create event cue for keyboard\n");
264  return 1;
265  }
266 
267  al_register_event_source(event_queue, al_get_keyboard_event_source());
268 
269  ALLEGRO_EVENT event;
270 
271  do {
272  al_wait_for_event(event_queue, &event);
273 
274  if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
275 
277  ts5_printf(x, y, "%s", str);
278 
279  ascii = event.keyboard.unichar;
280  if (ascii == 3 || ascii == 13) {
281  done = 1;
282  }
283  else if (ascii == 8 || ascii == 127) {
284  if (pos > 0)
285  pos--;
286  }
287  else if (ascii == 0) {
288 
289  }
290  else {
291  str[pos] = ascii;
292  pos++;
293  }
294 
295  if (pos > TS5_MAX_CHAR) {
296  pos = TS5_MAX_CHAR;
297  }
298  str[pos] = '\0';
300  ts5_printf(x, y, "%s", str);
302  }
303  } while (!done);
304 
305  al_unregister_event_source(event_queue, al_get_keyboard_event_source());
306  al_destroy_event_queue(event_queue);
307 
308  int i;
309  va_list args;
310  va_start(args, format);
311  i = vsscanf(str, format, args);
312  va_end(args);
313 
314  return i;
315 }
316 
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Get the width of a string without printing it.
320 ///
321 /// \param format Printf style format string.
322 ///
323 /// \return The width of the string on the display (in pixels).
324 ////////////////////////////////////////////////////////////////////////////////
325 double ts5_get_text_width(const char *format, ...)
326 {
327  ts5_check_textio("ts5_get_text_width");
328  ts5_log(TS5_LOGLEVEL_5, "ts5_get_text_width(...)\n");
329 
330  TS5_USTR *buf;
331  va_list ap;
332  int width;
333 
334  va_start(ap, format);
335  buf = al_ustr_new("");
336  al_ustr_vappendf(buf, format, ap);
337  va_end(ap);
338 
339  width = al_get_ustr_width(_ts5_status.graphics.font, buf);
340  al_ustr_free(buf);
341 
342  if (_ts5_status.graphics.coordinate_scale
343  == TS5_RELATIVE_COORDINATES) {
344  width/=_ts5_status.graphics.target_width;
345  }
346 
347  return width;
348 }
349 
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// Get the width of a UTF-8 string without printing it.
353 ///
354 /// \param ustr Unicode string.
355 ///
356 /// \return The width of the string on the display (in pixels).
357 ////////////////////////////////////////////////////////////////////////////////
358 double ts5_get_text_width_ustr(TS5_USTR *ustr)
359 {
360  ts5_check_textio("ts5_get_text_width_ustr");
361  ts5_log(TS5_LOGLEVEL_5, "ts5_get_text_width_ustr(...)\n");
362 
363  double width;
364  width = al_get_ustr_width(_ts5_status.graphics.font, ustr);
365 
366  if (_ts5_status.graphics.coordinate_scale
367  == TS5_RELATIVE_COORDINATES) {
368  width/=_ts5_status.graphics.target_width;
369  }
370 
371  return width;
372 }
373 
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 //@}
377 ////////////////////////////////////////////////////////////////////////////////
378 
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 /// @name Loading custom fonts
382 /// In Tscope5 three fonts are available as standard (courier, arial and times).
383 /// If these do not suit your needs any TrueType font that is installed
384 /// on your computer can be loaded manually.
385 //@{
386 ////////////////////////////////////////////////////////////////////////////////
387 
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Load a user defined font.
391 ///
392 /// \param fontfile Path to the file that describes the true type font.
393 /// \param size Size the font will be rendered in.
394 ///
395 /// \return A pointer to the TS5_FONT font structure.
396 ///
397 /// True type fonts can be found in /Library/fonts on Mac OS X.
398 ////////////////////////////////////////////////////////////////////////////////
399 TS5_FONT *ts5_read_font(const char *fontfile, double size)
400 {
401  ts5_check_textio("ts5_read_font");
402  ts5_log(TS5_LOGLEVEL_4, "ts5_read_font(%s,%f)\n", fontfile, size);
403 
404  ts5_log(TS5_LOGLEVEL_2, "ts5_read_font: loading font %s %f\n",
405  fontfile, size);
406 
407  TS5_FONT *font;
408  font = al_load_ttf_font(fontfile, -size, 0);
409 
410  if (!font) {
411  ts5_fatal("ts5_read_font: could not load font %s %d\n", fontfile,
412  _ts5_status.graphics.font_size);
413  }
414 
415  return font;
416 }
417 
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// Set a user defined font.
421 ///
422 /// \param font The new font.
423 ///
424 /// \return A pointer to the previous font.
425 ////////////////////////////////////////////////////////////////////////////////
426 TS5_FONT *ts5_set_font(TS5_FONT *font)
427 {
428  ts5_check_textio("ts5_set_font");
429  ts5_log(TS5_LOGLEVEL_4, "ts5_set_font(%p)\n", font);
430 
431  if (font == NULL) {
432  ts5_fatal("ts5_set_font: font is a NULL pointer\n");
433  }
434 
435  TS5_FONT *retval = _ts5_status.graphics.font;
436  _ts5_status.graphics.font = font;
437  _ts5_status.graphics.font_index = TS5_USERFONT;
438 
439  _ts5_status.graphics.font_size =
440  al_get_font_line_height(_ts5_status.graphics.font);
441 
442  return retval;
443 }
444 
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Free the memory used by a user defined font.
448 ///
449 /// \param font pointer to the font that will be freed.
450 ///
451 /// This function should be called at the end of the program for
452 /// each font read by the user.
453 ////////////////////////////////////////////////////////////////////////////////
454 void ts5_free_font(TS5_FONT *font)
455 {
456  ts5_check_textio("ts5_free_font");
457  ts5_log(TS5_LOGLEVEL_2, "ts5_free_font(%p)\n", font);
458 
459  if (font) {
460  al_destroy_font(font);
461  ts5_log(TS5_LOGLEVEL_2, "ts5_free_font: removed font\n");
462  font = NULL;
463  }
464 }
465 
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 //@}
469 ////////////////////////////////////////////////////////////////////////////////