1
// ---------------------------------------------------------------------------
3
// - standard object library - style class implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2015 amaury darsch -
15
// ---------------------------------------------------------------------------
21
#include "Utility.hpp"
22
#include "Boolean.hpp"
23
#include "Integer.hpp"
24
#include "Character.hpp"
25
#include "QuarkZone.hpp"
26
#include "Exception.hpp"
27
#include "InputStream.hpp"
28
#include "OutputStream.hpp"
32
// -------------------------------------------------------------------------
33
// - private section -
34
// -------------------------------------------------------------------------
36
// the text weight byte code
37
static const t_byte STL_WGHT_N = 0x00U;
38
static const t_byte STL_WGHT_B = 0x01U;
39
static const t_byte STL_WGHT_I = 0x02U;
40
// the text alignment byte code
41
static const t_byte STL_ALGN_L = 0x00U;
42
static const t_byte STL_ALGN_C = 0x01U;
43
static const t_byte STL_ALGN_R = 0x02U;
45
// this procedure converts a weight to a byte code
46
static t_byte stl_tobyte (const Style::t_wght wght) {
47
t_byte result = 0x00U;
62
// this procedure convert a byte code to a weight
63
static Style::t_wght stl_towght (const t_byte code) {
77
throw Exception ("style-error", "invalid text style serialization code");
80
// this procedure converts an alignment to a byte code
81
static t_byte stl_tobyte (const Style::t_algn algn) {
82
t_byte result = 0x00U;
97
// this procedure convert a byte code to an alignment
98
static Style::t_algn stl_toalgn (const t_byte code) {
101
return Style::ALGN_L;
104
return Style::ALGN_C;
107
return Style::ALGN_R;
112
throw Exception ("style-error", "invalid text position serialization code");
115
// this procedure returns a new style object for deserialization
116
static Serial* mksob (void) {
119
// register this style serial id
120
static const t_byte SERIAL_ID = Serial::setsid (SERIAL_STYL_ID, mksob);
122
// -------------------------------------------------------------------------
124
// -------------------------------------------------------------------------
126
// create a default style
128
Style::Style (void) {
132
// copy construct this style
134
Style::Style (const Style& that) {
137
d_wght = that.d_wght;
138
d_algn = that.d_algn;
139
d_tsiz = that.d_tsiz;
140
d_fill = that.d_fill;
141
d_psiz = that.d_psiz;
142
d_sflg = that.d_sflg;
150
// return the class name
152
String Style::repr (void) const {
156
// return a clone of this object
158
Object* Style::clone (void) const {
159
return new Style (*this);
162
// return the style serial code
164
t_byte Style::serialid (void) const {
165
return SERIAL_STYL_ID;
168
// serialize this style
170
void Style::wrstream (OutputStream& os) const {
173
// write the text style
174
os.write ((char) stl_tobyte (d_wght));
175
os.write ((char) stl_tobyte (d_algn));
176
Serial::wrlong (d_tsiz, os);
177
Serial::wrchar (d_fill, os);
178
// write the number formating
179
Serial::wrlong (d_psiz, os);
180
Serial::wrbool (d_sflg, os);
188
// deserialize this style
190
void Style::rdstream (InputStream& is) {
193
// read the test style
194
d_wght = stl_towght ((t_byte) is.read ());
195
d_algn = stl_toalgn ((t_byte) is.read ());
196
d_tsiz = Serial::rdlong (is);
197
d_fill = Serial::rdchar (is);
198
// get the number formating
199
d_psiz = Serial::rdlong (is);
200
d_sflg = Serial::rdbool (is);
208
// assign a style to this one
210
Style& Style::operator = (const Style& that) {
211
// check for self assignation
212
if (this == &that) return *this;
217
d_wght = that.d_wght;
218
d_algn = that.d_algn;
219
d_tsiz = that.d_tsiz;
220
d_fill = that.d_fill;
221
d_psiz = that.d_psiz;
222
d_sflg = that.d_sflg;
235
void Style::reset (void) {
251
// set the text weight
253
void Style::setwght (const t_wght wght) {
264
// get the text weight
266
Style::t_wght Style::getwght (void) const {
269
t_wght result = d_wght;
278
// set the text alignment
280
void Style::setalgn (const t_algn algn) {
291
// get the text alignment
293
Style::t_algn Style::getalgn (void) const {
296
t_algn result = d_algn;
307
void Style::settsiz (const long tsiz) {
311
throw Exception ("style-error", "invalid negative text size");
323
long Style::gettsiz (void) const {
326
long result = d_tsiz;
335
// set the filling character
337
void Style::setfill (const t_quad fill) {
348
// get the filling character
350
t_quad Style::getfill (void) const {
353
t_quad result = d_fill;
362
// set the number precision
364
void Style::setpsiz (const long psiz) {
368
throw Exception ("style-error", "invalid negative number precision");
378
// get the number precision
380
long Style::getpsiz (void) const {
383
long result = d_psiz;
392
// set the scientific flag
394
void Style::setsflg (const bool sflg) {
405
// get the scientific flag
407
bool Style::getsflg (void) const {
410
bool result = d_sflg;
419
// convert an integer number into a string - no style
421
String Style::format (const long ival) const {
424
String result = Utility::tostring (ival, d_psiz);
433
// convert an integer number into a string - no style
435
String Style::format (const t_long ival) const {
438
String result = Utility::tostring (ival, d_psiz);
447
// convert a real number into a string - no style
449
String Style::format (const t_real rval) const {
452
String result = Utility::tostring (rval, d_psiz, d_sflg);
461
// format a string with the text style
463
String Style::format (const String& sval, const long size) const {
466
// format the result string using non combining length
468
long slen = sval.ncclen ();
469
// check if we process the size or not
472
if (d_algn == ALGN_R) {
473
result = sval.lfill (d_fill, size);
475
result = sval.rfill (d_fill, size);
481
if (slen == d_tsiz) result = sval;
483
if (d_algn == ALGN_R) {
484
result = sval.lfill (d_fill, d_tsiz);
486
result = sval.rfill (d_fill, d_tsiz);
490
if (d_algn == ALGN_R) {
491
result = sval.lsubstr (d_tsiz);
493
result = sval.rsubstr (slen - d_tsiz);
505
// -------------------------------------------------------------------------
506
// - object section -
507
// -------------------------------------------------------------------------
509
// the object eval quarks
510
static const long QUARK_WGHTN = String::intern ("WEIGHT-NORMAL");
511
static const long QUARK_WGHTB = String::intern ("WEIGHT-BOLD");
512
static const long QUARK_WGHTI = String::intern ("WEIGHT-ITALIC");
513
static const long QUARK_ALGNL = String::intern ("ALIGN-LEFT");
514
static const long QUARK_ALGNC = String::intern ("ALIGN-CENTER");
515
static const long QUARK_ALGNR = String::intern ("ALIGN-RIGHT");
516
static const long QUARK_STYLE = String::intern ("Style");
519
static const long QUARK_ZONE_LENGTH = 13;
520
static QuarkZone zone (QUARK_ZONE_LENGTH);
522
// the object supported quarks
523
static const long QUARK_RESET = zone.intern ("reset");
524
static const long QUARK_SETTSIZ = zone.intern ("set-text-size");
525
static const long QUARK_GETTSIZ = zone.intern ("get-text-size");
526
static const long QUARK_SETFILL = zone.intern ("set-text-fill");
527
static const long QUARK_GETFILL = zone.intern ("get-text-fill");
528
static const long QUARK_SETWGHT = zone.intern ("set-text-weight");
529
static const long QUARK_GETWGHT = zone.intern ("get-text-weight");
530
static const long QUARK_SETALGN = zone.intern ("set-text-alignment");
531
static const long QUARK_GETALGN = zone.intern ("get-text-alignment");
532
static const long QUARK_SETPSIZ = zone.intern ("set-number-precision");
533
static const long QUARK_GETPSIZ = zone.intern ("get-number-precision");
534
static const long QUARK_SETSFLG = zone.intern ("set-scientific-notation");
535
static const long QUARK_GETSFLG = zone.intern ("get-scientific-notation");
537
// map an item to a weight type
538
static inline Style::t_wght item_to_wght (const Item& item) {
539
// check for a stream item
540
if (item.gettid () != QUARK_STYLE) {
541
throw Exception ("item-error", "item is not a style item");
543
// map the item to the enumeration
544
long quark = item.getquark ();
545
if (quark == QUARK_WGHTN) return Style::WGHT_N;
546
if (quark == QUARK_WGHTB) return Style::WGHT_B;
547
if (quark == QUARK_WGHTI) return Style::WGHT_I;
548
throw Exception ("item-error", "cannot map item to weight type");
551
// map a weight type to an item
552
static inline Item* wght_to_item (const Style::t_wght wght) {
556
result = new Item (QUARK_STYLE, QUARK_WGHTN);
559
result = new Item (QUARK_STYLE, QUARK_WGHTB);
562
result = new Item (QUARK_STYLE, QUARK_WGHTI);
568
// map an item to an alignment type
569
static inline Style::t_algn item_to_algn (const Item& item) {
570
// check for a stream item
571
if (item.gettid () != QUARK_STYLE) {
572
throw Exception ("item-error", "item is not a style item");
574
// map the item to the enumeration
575
long quark = item.getquark ();
576
if (quark == QUARK_ALGNL) return Style::ALGN_L;
577
if (quark == QUARK_ALGNC) return Style::ALGN_C;
578
if (quark == QUARK_ALGNR) return Style::ALGN_R;
579
throw Exception ("item-error", "cannot map item to alignment type");
582
// map an alignment type to an item
583
static inline Item* algn_to_item (const Style::t_algn algn) {
587
result = new Item (QUARK_STYLE, QUARK_ALGNL);
590
result = new Item (QUARK_STYLE, QUARK_ALGNC);
593
result = new Item (QUARK_STYLE, QUARK_ALGNR);
599
// create a new object in a generic way
601
Object* Style::mknew (Vector* argv) {
602
// get number of arguments
603
long argc = (argv == nilp) ? 0 : argv->length ();
604
// check for 0 argument
605
if (argc == 0) return new Style;
607
throw Exception ("argument-error", "too many arguments with style");
610
// evaluate a quark statically
612
Object* Style::meval (Runnable* robj, Nameset* nset, const long quark) {
613
if (quark == QUARK_WGHTN)
614
return new Item (QUARK_STYLE, QUARK_WGHTN);
615
if (quark == QUARK_WGHTB)
616
return new Item (QUARK_STYLE, QUARK_WGHTB);
617
if (quark == QUARK_WGHTI)
618
return new Item (QUARK_STYLE, QUARK_WGHTI);
619
if (quark == QUARK_ALGNL)
620
return new Item (QUARK_STYLE, QUARK_ALGNL);
621
if (quark == QUARK_ALGNC)
622
return new Item (QUARK_STYLE, QUARK_ALGNC);
623
if (quark == QUARK_ALGNR)
624
return new Item (QUARK_STYLE, QUARK_ALGNR);
625
throw Exception ("eval-error", "cannot evaluate member",
626
String::qmap (quark));
629
// return true if the given quark is defined
631
bool Style::isquark (const long quark, const bool hflg) const {
634
if (zone.exists (quark) == true) {
638
bool result = hflg ? Serial::isquark (quark, hflg) : false;
647
// apply this object with a set of arguments and a quark
649
Object* Style::apply (Runnable* robj, Nameset* nset, const long quark,
651
// get the number of arguments
652
long argc = (argv == nilp) ? 0 : argv->length ();
654
// dispatch 0 argument
656
if (quark == QUARK_GETWGHT) return wght_to_item (getwght ());
657
if (quark == QUARK_GETALGN) return algn_to_item (getalgn ());
658
if (quark == QUARK_GETTSIZ) return new Integer (gettsiz ());
659
if (quark == QUARK_GETFILL) return new Character (getfill ());
660
if (quark == QUARK_GETPSIZ) return new Integer (getpsiz ());
661
if (quark == QUARK_GETSFLG) return new Boolean (getsflg ());
662
if (quark == QUARK_RESET) {
667
// dispatch 1 argument
669
if (quark == QUARK_SETWGHT) {
670
Object* obj = argv->get (0);
671
Item* iobj = dynamic_cast <Item*> (obj);
673
throw Exception ("type-error", "invalid object for item type",
676
setwght (item_to_wght (*iobj));
679
if (quark == QUARK_SETALGN) {
680
Object* obj = argv->get (0);
681
Item* iobj = dynamic_cast <Item*> (obj);
683
throw Exception ("type-error", "invalid object for item type",
686
setalgn (item_to_algn (*iobj));
689
if (quark == QUARK_SETTSIZ) {
690
long tsiz = argv->getlong (0);
694
if (quark == QUARK_SETFILL) {
695
t_quad fill = argv->getchar (0);
699
if (quark == QUARK_SETPSIZ) {
700
long psiz = argv->getlong (0);
704
if (quark == QUARK_SETSFLG) {
705
bool sflg = argv->getbool (0);
710
// call the serial method
711
return Serial::apply (robj, nset, quark, argv);