source: trunk/Mars/mbase/MEnv.cc @ 19273

Last change on this file since 19273 was 19086, checked in by tbretz, 16 months ago
pos is a pointer, must be !=0 not >0
File size: 34.1 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18!   Author(s): Thomas Bretz  2/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20!   Copyright: MAGIC Software Development, 2000-2009
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27//  MEnv
28//
29// It is a slightly changed version of TEnv. It logs all resources which are
30// touched, so that you can print all untouched resources by
31// PrintUntouched()
32//
33// A new special resource is available. With the resource "Include"
34// you can include resources from other files, for example
35//
36//   Include: file1.rc file2.rc
37//
38// Including can be done recursively. Resources from the included files
39// have lower priority. This allows to write a resource file with your
40// default resources which then can be included in other files overwriting
41// some of the resources.
42//
43// If given paths are not absolute there base is always th elocation of
44// the including file.
45//
46// Class Version 1:
47// ----------------
48//  + TString fName
49//
50//////////////////////////////////////////////////////////////////////////////
51#include "MEnv.h"
52
53#include <fstream>
54#include <exception>
55
56#include <Gtypes.h>
57#include <TObjString.h>
58#include <TObjArray.h>
59
60#include <TPave.h>
61#include <TAttText.h>
62#include <TAttMarker.h>
63#include <THashList.h>   // needed since root v5.10/00 (TEnv::GetTable)
64
65#include "MLog.h"
66#include "MLogManip.h"
67
68#include "MArgs.h"
69#include "MString.h"
70
71ClassImp(MEnv);
72
73using namespace std;
74
75//---------------------------------------------------------------------------
76//
77// (Default) constructor. If the given file cannot be accessed SetRcName("")
78// is called which can then be checked by IsValid()
79//
80// The second argument is the default name. Usually as name of the MEnv
81// the base name of the file is returned. By giving a default name
82// you can overwrite this behavious. This is useful for I/O
83// because it allows to use Read and Write without argument.
84//
85MEnv::MEnv(const char *name, const char *defname) : TEnv(name), fName(defname)
86{
87    fChecked.SetOwner();
88
89    // If TEnv::TEnv has not set fRcName
90    if (!IsValid())
91        return;
92
93    // ExpandPathName (not done by TEnv::TEnv) and read again
94    TString fname(name);
95    gSystem->ExpandPathName(fname);
96
97    // Is file accessible
98    if (gSystem->AccessPathName(fname, kFileExists))
99        fname = "";
100
101    SetRcName(fname);
102   
103    if (!IsTEnvCompliant(name)){
104        throw "This file can't be correctly parsed by TEnv";
105        return;
106    }
107
108    // No file found
109    if (fname.IsNull())
110        return;
111
112    // File has been already processed, but ReadInclude is part of a
113    // derived function, i.e. not yet executed.
114    if (GetEntries()>0 || fname==name)
115    {
116        if (ReadInclude()<0)
117            SetRcName("");
118        return;
119    }
120
121    // File not yet processed. Reread file.
122    if (ReadFile(fname, kEnvLocal)<0)
123        SetRcName("");
124}
125
126//---------------------------------------------------------------------------
127//
128// Process an Include directive and read the corresponding contents
129//
130Int_t MEnv::ReadInclude()
131{
132    // Check for "Include" resource
133    const TString incl = GetValue("Include", "");
134    if (incl.IsNull())
135        return 0;
136
137    const char *dir = gSystem->DirName(GetRcName());
138
139    // Tokenize the array into single files divided by a whitespace
140    TObjArray *arr = incl.Tokenize(" ");
141
142    // We have to rebuild the Include array from scratch to get the
143    // correct sorting for a possible rereading.
144    SetValue("Include", "");
145
146    // FIXME: Make sure that recursions don't crash the system!
147
148    for (int i=0; i<arr->GetEntries(); i++)
149    {
150        // Get file name to include
151        TString fenv = (*arr)[i]->GetName();
152
153        // If the is not anabsolute path we prepend the dir-name
154        // of the including file. This allows that includes
155        // do not necessarily need absolute paths and paths are always
156        // relative to the location of th eincluding file.
157        if (!gSystem->IsAbsoluteFileName(fenv))
158        {
159            fenv.Prepend("/");
160            fenv.Prepend(dir);
161        }
162
163        // Read included file and check if its valid
164        const MEnv env(fenv);
165        if (!env.IsValid())
166        {
167            delete arr;
168            return -1;
169        }
170
171        // Add file name before its childs
172        SetValue("+Include", fenv);
173
174        // If it is valid add entries from include without overwriting,
175        // i.e. the included resources have lower priority
176        AddEnv(env, kFALSE);
177
178        // Get a possible child include from env
179        const TString incl2 = const_cast<MEnv&>(env).GetValue("Include", "");
180        if (!incl2.IsNull())
181            SetValue("+Include", incl2);
182    }
183
184    delete arr;
185
186    // Get final compiled resource
187    TString inc = GetValue("Include", "");
188
189    // Remove obsolete whitespaces for convinience
190    inc.ReplaceAll("  ", " ");
191    inc = inc.Strip(TString::kBoth);
192
193    // Set final resource, now as kEnvLocal (previously set as kEnvChanged)
194    SetValue("Include", inc, kEnvLocal);
195
196    // FIXME: Remove douplets in the correct order
197
198    return 0;
199}
200
201//---------------------------------------------------------------------------
202//
203// Check if the input file is compatible to the way TEnv parses a resource file.
204//
205// Returns true in case everything is file and
206//         false in case there is a problem with the file.
207//
208// Background:
209//      This check has been introduced as a workaround for a ROOT feature.
210//      TEnv will not see the last line in a text file, when this last line
211//      does not end with a \n.
212//
213//      In addition we check for the occurence of \r, since some editors would
214//      place \r instead of \n (unlike windows that uses \n\r), which would
215//      also result in problems.
216//      FIXME: So currently we also complain about "\n\r" and "\r\n" as well as
217//      "\r  \t   \n" or "\n      \t\t\t\r", which would in fact not be a problem at
218//      all.
219Bool_t MEnv::IsTEnvCompliant(const char *fname)
220{
221    ifstream ifs(fname);
222    bool printable_char_since_last_lf = false;
223    char c;
224    while (ifs.good()){
225        ifs.get(c);
226
227        if (c==13){
228            gLog << err << "Menv::IsTEnvCompliant - file:" << fname
229                << " contains \\r this might lead to parsing errors. "
230                <<"Please exchange \\r by \\n everywhere in that file." 
231                << endl;
232            return false;
233        }
234        if (c=='\n'){
235            printable_char_since_last_lf = false;
236        }
237        if (isgraph(c)){
238            printable_char_since_last_lf = true;
239        }
240    }
241    if (printable_char_since_last_lf){
242        gLog << err << "Menv::IsTEnvCompliant - file:" << fname
243            << " must have \\n at the end of the file. "
244            <<"Please make sure this is the case." 
245            << endl;
246        return false;
247    }
248    return true;
249}
250
251//---------------------------------------------------------------------------
252//
253// Read and parse the resource file for a certain level.
254// Returns -1 on case of error, 0 in case of success.
255//
256// Check for an include directive
257//
258Int_t MEnv::ReadFile(const char *fname, EEnvLevel level)
259{
260    // First read the file via TEnv
261    if (TEnv::ReadFile(fname, level)<0)
262        return -1;
263
264    return ReadInclude();
265}
266
267// --------------------------------------------------------------------------
268//
269// Read an object from the current directory. If no name is given
270// the name of this object is used.
271//
272Int_t MEnv::Read(const char *name)
273{
274    const Int_t rc = TEnv::Read(name?name:(const char*)fName);
275    //if (name)
276    //    SetName(name);
277    return rc;
278}
279
280//---------------------------------------------------------------------------
281//
282// Make sure that the name used for writing doesn't contain a full path
283//
284const char *MEnv::GetName() const
285{
286    if (!fName.IsNull())
287        return fName;
288
289    const char *pos = strrchr(GetRcName(), '/');
290    return pos ? pos+1 : GetRcName();
291}
292
293//---------------------------------------------------------------------------
294//
295// Return the total number of entries in the table
296//
297Int_t MEnv::GetEntries() const
298{
299    if (!GetTable())
300        return -1;
301
302    return GetTable()->GetEntries();
303}
304
305//---------------------------------------------------------------------------
306//
307// Compile str+post and make sure that in between there is a unique dot.
308//
309TString MEnv::Compile(TString str, const char *post) const
310{
311    if (!str.IsNull() && !str.EndsWith("."))
312        str += ".";
313
314    str += post;
315
316    return str;
317}
318
319//---------------------------------------------------------------------------
320//
321// Get the value from the table and remember the value as checked
322//
323Int_t MEnv::GetValue(const char *name, Int_t dflt)
324{
325    if (!fChecked.FindObject(name))
326        fChecked.Add(new TObjString(name));
327    return TEnv::GetValue(name, dflt);
328}
329
330//---------------------------------------------------------------------------
331//
332// Get the value from the table and remember the value as checked
333//
334Double_t MEnv::GetValue(const char *name, Double_t dflt)
335{
336    if (!fChecked.FindObject(name))
337        fChecked.Add(new TObjString(name));
338    return TEnv::GetValue(name, dflt);
339}
340
341//---------------------------------------------------------------------------
342//
343// Get the value from the table and remember the value as checked
344//
345const char *MEnv::GetValue(const char *name, const char *dflt)
346{
347    if (!fChecked.FindObject(name))
348        fChecked.Add(new TObjString(name));
349    return TEnv::GetValue(name, dflt);
350}
351
352//---------------------------------------------------------------------------
353//
354// TEnv doen't have a streamer --> cannot be cloned
355//   --> we have to clone it ourself
356//
357TObject *MEnv::Clone(const char *) const
358{
359    MEnv *env = new MEnv("/dev/null");
360    env->SetRcName(GetRcName());
361    env->AddEnv(*this);
362    return env;
363}
364
365//---------------------------------------------------------------------------
366//
367// Interprete fill style: Hollow, Solid, Hatch, 0%-100%
368// If no text style is detected the value is converted to an integer.
369//
370Int_t MEnv::GetFillStyle(const char *name, Int_t dftl)
371{
372    TString str = GetValue(name, "");
373    str = str.Strip(TString::kBoth);
374    if (str.IsNull())
375        return dftl;
376
377    str.ToLower();
378
379    switch (str.Hash())
380    {
381    case 2374867578U: return 0;    // hollow
382    case  764279305U: return 1001; // solid
383    case 1854683492U: return 2001; // hatch
384    }
385
386    return str.EndsWith("%") ? 4000+str.Atoi() : str.Atoi();
387}
388
389//---------------------------------------------------------------------------
390//
391// Interprete line style: Solid, Dashed, Dotted, DashDotted
392// If no line style is detected the value is converted to an integer.
393//
394Int_t MEnv::GetLineStyle(const char *name, Int_t dftl)
395{
396    TString str = GetValue(name, "");
397    str = str.Strip(TString::kBoth);
398    if (str.IsNull())
399        return dftl;
400
401    str.ToLower();
402
403    switch (str.Hash())
404    {
405    case  764279305U: return kSolid;
406    case  241979881U: return kDashed;
407    case 2391642602U: return kDotted;
408    case 1124931659U: return kDashDotted;
409    }
410
411    return str.Atoi();
412}
413
414//---------------------------------------------------------------------------
415//
416// Interprete alignment: Top, Right, Left, Bottom, Center, tr, cc, bl, ...
417// If no text align is detected the value is converted to an integer.
418//
419//  eg.
420//    Top Right
421//    Bottom Center
422//    Center
423//    tr
424//    br
425//    cr
426//
427Int_t MEnv::GetAlign(const char *name, Int_t dftl)
428{
429    TString str = GetValue(name, "");
430    str = str.Strip(TString::kBoth);
431    if (str.IsNull())
432        return dftl;
433
434    str.ToLower();
435
436    switch (str.Hash())
437    {
438    case 29746: return 33; // tr
439    case 25379: return 22; // cc
440    case 25132: return 11; // bl
441
442    case 25388: return 12; // cl
443    case 25394: return 32; // cr
444
445    case 29731: return 23; // tc
446    case 25123: return 32; // bc
447
448    case 29740: return 13; // tl
449    case 25138: return 13; // br
450    }
451
452    Int_t align = 0;
453    if (str.Contains("right", TString::kIgnoreCase))
454        align += 3;
455    if (str.Contains("left", TString::kIgnoreCase))
456        align += 1;
457    if (str.Contains("bottom", TString::kIgnoreCase))
458        align += 10;
459    if (str.Contains("top", TString::kIgnoreCase))
460        align += 30;
461
462    if (str.Contains("center", TString::kIgnoreCase))
463    {
464        if (align==0)
465            return 22;
466        if (align/10==0)
467            return align+20;
468        if (align%10==0)
469            return align+2;
470    }
471
472    return align>0 ? align : str.Atoi();
473}
474
475//---------------------------------------------------------------------------
476//
477// Interprete color: Black, White, Red, Green, Blue, Yellow, Magenta,
478// Cyan, Gray1-5, Grey1-5.
479// If no text color is detected the value is converted to an integer.
480//
481//  eg.
482//    Red
483//    Light Red
484//    Dark Red
485//
486Int_t MEnv::GetColor(const char *name, Int_t dftl)
487{
488    TString str = GetValue(name, "");
489
490    str = str.Strip(TString::kBoth);
491    if (str.IsNull())
492        return dftl;
493
494    str.ToLower();
495
496    Int_t offset=0;
497    if (str.Contains("dark"))
498    {
499        str.ReplaceAll("dark", "");
500        str = str.Strip(TString::kBoth);
501        offset = 100;
502    }
503    if (str.Contains("light"))
504    {
505        str.ReplaceAll("light", "");
506        str = str.Strip(TString::kBoth);
507        offset = 150;
508    }
509
510    switch (str.Hash())
511    {
512    case 2368543371U: return kWhite+offset;
513    case 1814927399U: return kBlack+offset;
514    case    7496964U: return kRed+offset;
515    case 2897107074U: return kGreen+offset;
516    case 1702194402U: return kBlue+offset;
517    case 2374817882U: return kYellow+offset;
518    case 2894218701U: return kMagenta+offset;
519    case 1851881955U: return kCyan+offset;
520    case  749623518U: return 19; // grey1
521    case  749623517U: return 18; // grey2
522    case  749623516U: return 17; // grey3
523    case  749623515U: return 16; // grey4
524    case  749623514U: return 15; // grey5
525    case  749623513U: return 14; // grey6
526    case  749623512U: return 13; // grey7
527    case  749623511U: return 12; // grey8
528    case  741234910U: return 19; // gray1
529    case  741234909U: return 18; // gray2
530    case  741234908U: return 17; // gray3
531    case  741234907U: return 16; // gray4
532    case  741234906U: return 15; // gray5
533    case  741234905U: return 14; // gray6
534    case  741234904U: return 13; // gray7
535    case  741234903U: return 12; // gray8
536    }
537    return str.Atoi();
538}
539
540//---------------------------------------------------------------------------
541//
542// As possible convert the color col into a text string which can be
543// interpreted by GetColor before setting the resource value
544//
545void MEnv::SetColor(const char *name, Int_t col)
546{
547    TString val;
548
549    if (col>99 && col<101+kCyan)
550    {
551        val = "Dark ";
552        col -= 100;
553    }
554    if (col>150 && col<151+kCyan)
555    {
556        val = "Light ";
557        col -= 150;
558    }
559
560    switch (col)
561    {
562    case kWhite:   val += "White";   break;
563    case kBlack:   val += "Black";   break;
564    case kRed:     val += "Red";     break;
565    case kGreen:   val += "Green";   break;
566    case kBlue:    val += "Blue";    break;
567    case kYellow:  val += "Yellow";  break;
568    case kMagenta: val += "Magenta"; break;
569    case kCyan:    val += "Cyan";    break;
570    case 19:       val += "Grey1";   break;
571    case 18:       val += "Grey2";   break;
572    case 17:       val += "Grey3";   break;
573    case 16:       val += "Grey4";   break;
574    case 15:       val += "Grey5";   break;
575    case 14:       val += "Grey6";   break;
576    case 13:       val += "Grey7";   break;
577    case 12:       val += "Grey8";   break;
578    }
579
580    if (val.IsNull())
581        val += col;
582
583    SetValue(name, val);
584}
585
586//---------------------------------------------------------------------------
587//
588// As possible convert the alignment align into a text string which can be
589// interpreted by GetAlign before setting the resource value
590//
591void MEnv::SetAlign(const char *name, Int_t align)
592{
593    TString val;
594    if (align==22)
595    {
596        SetValue(name, "Center");
597        return;
598    }
599
600    switch (align%10)
601    {
602    case 1: val += "Left";   break;
603    case 2: val += "Center"; break;
604    case 3: val += "Right";  break;
605    }
606
607    switch (align/10)
608    {
609    case 1: val += "Bottom"; break;
610    case 2: val += "Center"; break;
611    case 3: val += "Top";    break;
612    }
613
614    SetValue(name, val);
615}
616
617//---------------------------------------------------------------------------
618//
619// As possible convert the fill style style into a text string which can be
620// interpreted by GetFillStyle before setting the resource value
621//
622void MEnv::SetFillStyle(const char *name, Int_t style)
623{
624    TString val;
625
626    if (style>3999 && style<4101)
627        val = MString::Format("%d%%", style-4000);
628
629    switch (style)
630    {
631    case 0:    val = "Hollow"; break;
632    case 1001: val = "Solid";  break;
633    case 2001: val = "Hatch";  break;
634    }
635
636    if (val.IsNull())
637        val += style;
638
639    SetValue(name, val);
640}
641
642//---------------------------------------------------------------------------
643//
644// As possible convert the line style style into a text string which can be
645// interpreted by GetLineStyle before setting the resource value
646//
647void MEnv::SetLineStyle(const char *name, Int_t style)
648{
649    TString val;
650    switch (style)
651    {
652    case kSolid:      val = "Solid";       break;
653    case kDashed:     val = "Dashed";      break;
654    case kDotted:     val = "Dotted";      break;
655    case kDashDotted: val = "DashDotted";  break;
656    }
657
658    if (val.IsNull())
659        val += style;
660
661    SetValue(name, val);
662}
663
664//---------------------------------------------------------------------------
665//
666// As possible convert the marker style style into a text string which can be
667// interpreted by GetLineStyle before setting the resource value
668//
669void MEnv::SetMarkerStyle(const char *name, Int_t style)
670{
671    TString val;
672    switch (style)
673    {
674    case kDot:              val = "dot";
675    case kPlus:             val = "plus";
676    case kCircle:           val = "circle";
677    case kMultiply:         val = "multiply";
678    case kFullDotSmall:     val = "fulldotsmall";
679    case kFullDotMedium:    val = "fulldotmedium";
680    case kFullDotLarge:     val = "fulldotlarge";
681//    case kOpenTriangleDown: val = "opentriangledown";
682//    case kFullCross:        val = "fullcross";
683    case kFullCircle:       val = "fullcircle";
684    case kFullSquare:       val = "fullsquare";
685    case kFullTriangleDown: val = "fulltriangledown";
686    case kOpenCircle:       val = "opencircle";
687    case kOpenSquare:       val = "opensquare";
688    case kOpenTriangleUp:   val = "opentriangleup";
689    case kOpenDiamond:      val = "opendiamond";
690    case kOpenCross:        val = "opencross";
691    case kFullStar:         val = "fullstar";
692    case kOpenStar:         val = "openstar";
693    }
694
695    if (val.IsNull())
696        val += style;
697
698    SetValue(name, val);
699}
700
701//---------------------------------------------------------------------------
702//
703// Get the attributed from a TAttLine (if dftl is given use it as default)
704//   name.LineColor  <see also GetColor>
705//   name.LineStyle
706//   name.LineWidth
707// For more details on the meaning see TAttLine
708//
709void MEnv::GetAttLine(const char *name, TAttLine &line, TAttLine *dftl)
710{
711    const TString color = Compile(name, "LineColor");
712    const TString style = Compile(name, "LineStyle");
713    const TString width = Compile(name, "LineWidth");
714
715    if (!dftl)
716        dftl = &line;
717
718    const Color_t col = GetColor(color, dftl->GetLineColor());
719    const Style_t sty = GetLineStyle(style, dftl->GetLineStyle());
720    const Style_t wid = GetValue(width, dftl->GetLineWidth());
721
722    line.SetLineColor(col);
723    line.SetLineStyle(sty);
724    line.SetLineWidth(wid);
725}
726
727//---------------------------------------------------------------------------
728//
729// Get the attributed from a TAttText (if dftl is given use it as default)
730//   name.TextColor  <see also GetColor>
731//   name.TextAlign  <see also GetAlign>
732//   name.TextAngle
733//   name.TextFont
734//   name.TextSize
735// For more details on the meaning see TAttText
736//
737void MEnv::GetAttText(const char *name, TAttText &text, TAttText *dftl)
738{
739   const TString color = Compile(name, "TextColor");
740   const TString align = Compile(name, "TextAlign");
741   const TString angle = Compile(name, "TextAngle");
742   const TString font  = Compile(name, "TextFont");
743   const TString size  = Compile(name, "TextSize");
744
745    if (!dftl)
746        dftl = &text;
747
748    const Color_t col = GetColor(color, dftl->GetTextColor());
749    const Short_t ali = GetAlign(align, dftl->GetTextAlign());
750    const Float_t ang = GetValue(angle, dftl->GetTextAngle());
751    const Font_t  fon = GetValue(font,  dftl->GetTextFont());
752    const Float_t siz = GetValue(size,  dftl->GetTextSize());
753
754    text.SetTextColor(col);
755    text.SetTextAlign(ali);
756    text.SetTextAngle(ang);
757    text.SetTextFont(fon);
758    text.SetTextSize(siz);
759}
760
761//---------------------------------------------------------------------------
762//
763// Get the attributed from a TAttFill (if dftl is given use it as default)
764//   name.FillColor  <see also GetColor>
765//   name.FillStyle  <see also GetFillStyle>
766// For more details on the meaning see TAttFill
767//
768void MEnv::GetAttFill(const char *name, TAttFill &fill, TAttFill *dftl)
769{
770    const TString color = Compile(name, "FillColor");
771    const TString style = Compile(name, "FillStyle");
772
773    if (!dftl)
774        dftl = &fill;
775
776    const Color_t col = GetColor(color, dftl->GetFillColor());
777    const Style_t sty = GetFillStyle(style, dftl->GetFillStyle());
778 
779    fill.SetFillColor(col);
780    fill.SetFillStyle(sty);
781}
782
783//---------------------------------------------------------------------------
784//
785// Get the attributed from a TAttMarker (if dftl is given use it as default)
786//   name.MarkerColor  <see also GetColor>
787//   name.MarkerStyle
788//   name.MarkerSize
789// For more details on the meaning see TAttMarker
790//
791void MEnv::GetAttMarker(const char *name, TAttMarker &marker, TAttMarker *dftl)
792{
793    const TString color = Compile(name, "MarkerColor");
794    const TString style = Compile(name, "MarkerStyle");
795    const TString size  = Compile(name, "MarkerSize");
796
797    if (!dftl)
798        dftl = &marker;
799
800    const Color_t col = GetColor(color, dftl->GetMarkerColor());
801    const Style_t sty = GetValue(style, dftl->GetMarkerStyle());
802    const Size_t  siz = GetValue(size,  dftl->GetMarkerSize());
803
804    marker.SetMarkerColor(col);
805    marker.SetMarkerStyle(sty);
806    marker.SetMarkerSize(siz);
807}
808
809//---------------------------------------------------------------------------
810//
811// Get the attributed from a TPave (if dftl is given use it as default)
812//   name.CornerRadius
813//   name.BorderSize
814//   name.Option
815// Also all resources from TAttLine and TAttFill are supported.
816//
817// For your conveinience: If the CornerRadius is greater than 0 "arc" is
818// added to the options. If it is equal or less than 0 "arc" is removed
819// from the options.
820//
821// For more details on the meaning see TPave
822//
823void MEnv::GetAttPave(const char *str, TPave &pave, TPave *dftl)
824{
825    const TString post(str);
826
827    TString name(pave.GetName());
828    if (!name.IsNull() && name!=pave.ClassName())
829        name = Compile(name, post);
830
831    GetAttLine(name, pave, dftl);
832    GetAttFill(name, pave, dftl);
833
834    const TString corner = Compile(name, "CornerRadius");
835    const TString border = Compile(name, "BorderSize");
836    const TString option = Compile(name, "Option");
837
838    if (!dftl)
839        dftl = &pave;
840
841    const Double_t cor = GetValue(corner, dftl->GetCornerRadius());
842    const Int_t    bor = GetValue(border, dftl->GetBorderSize());
843
844    pave.SetCornerRadius(cor);
845    pave.SetBorderSize(bor);
846
847    TString  opt = GetValue(option, dftl->GetOption());
848    opt.ToLower();
849
850    const Bool_t has = pave.GetCornerRadius()>0;
851
852    if (has && !opt.Contains("arc"))
853        opt += "arc";
854
855    if (!has && opt.Contains("arc"))
856        opt.ReplaceAll("arc", "");
857
858    pave.SetOption(opt);
859
860}
861
862//---------------------------------------------------------------------------
863//
864// Get the attributed for the TObject obj. Use dftl for default attributes
865// if given.
866//
867// There is support for:
868//    TPave      <see GetAttPave>
869//    TAttLine   <see GetAttLine>
870//    TAttText   <see GetAttText>
871//    TAttFill   <see GetAttFill>
872//    TAttMarker <see GetAttMarker>
873//
874void MEnv::GetAttributes(const char *name, TObject *obj, TObject *dftl)
875{
876    //TAttAxis         *line = dynamic_cast<TAttAxis*>(obj);
877    //TAtt3D           *line = dynamic_cast<TAtt3D*>(obj);
878    //TAttCanvas       *line = dynamic_cast<TAttCanvas*>(obj);
879    //TAttFillCanvas   *line = dynamic_cast<TAttFillEitor*>(obj);
880    //TAttLineCanvas   *line = dynamic_cast<TAttLineCanvas*>(obj);
881    //TAttLineEditor   *line = dynamic_cast<TAttLineEditor*>(obj);
882    //TAttMarkerCanvas *line = dynamic_cast<TAttMarkerCanvas*>(obj);
883    //TAttMarkerEditor *line = dynamic_cast<TAttMarkerEditor*>(obj);
884    //TAttPad          *line = dynamic_cast<TAttPad*>(obj);
885    //TAttParticle     *line = dynamic_cast<TAttParticle*>(obj);
886    //TAttTextCanvas   *line = dynamic_cast<TAttTextCanvas*>(obj);
887    //TAttTextEditor   *line = dynamic_cast<TAttTextEditor*>(obj);
888
889    TPave      *pave = dynamic_cast<TPave*>(obj);
890    TAttLine   *line = dynamic_cast<TAttLine*>(obj);
891    TAttText   *text = dynamic_cast<TAttText*>(obj);
892    TAttFill   *fill = dynamic_cast<TAttFill*>(obj);
893    TAttMarker *mark = dynamic_cast<TAttMarker*>(obj);
894
895    if (pave)
896    {
897        GetAttPave(name, *pave, dynamic_cast<TPave*>(dftl));
898        return;
899    }
900
901    if (line)
902        GetAttLine(name, *line, dynamic_cast<TAttLine*>(dftl));
903    if (text)
904        GetAttText(name, *text, dynamic_cast<TAttText*>(dftl));
905    if (fill)
906        GetAttFill(name, *fill, dynamic_cast<TAttFill*>(dftl));
907    if (mark)
908        GetAttMarker(name, *mark, dynamic_cast<TAttMarker*>(dftl));
909}
910
911//---------------------------------------------------------------------------
912//
913// Set the resources from a TAttLine:
914//   name.LineColor  <see also SetColor>
915//   name.LineStyle
916//   name.LineWidth
917//
918void MEnv::SetAttLine(const char *name, const TAttLine &line)
919{
920    const TString color = Compile(name, "LineColor");
921    const TString style = Compile(name, "LineStyle");
922    const TString width = Compile(name, "LineWidth");
923
924    SetColor(color, line.GetLineColor());
925    SetLineStyle(style, line.GetLineStyle());
926    SetValue(width, line.GetLineWidth());
927}
928
929//---------------------------------------------------------------------------
930//
931// Set the resources from a TAttText:
932//   name.TextColor  <see also SetColor>
933//   name.TextAlign  <see also SetAlign>
934//   name.TextAngle
935//   name.TextFont
936//   name.TextSize
937//
938void MEnv::SetAttText(const char *name, const TAttText &text)
939{
940    const TString color = Compile(name, "TextColor");
941    const TString align = Compile(name, "TextAlign");
942    const TString angle = Compile(name, "TextAngle");
943    const TString font  = Compile(name, "TextFont");
944    const TString size  = Compile(name, "TextSize");
945
946    SetColor(color, text.GetTextColor());
947    SetAlign(align, text.GetTextAlign());
948    SetValue(angle, text.GetTextAngle());
949    SetValue(font,  text.GetTextFont());
950    SetValue(size,  text.GetTextSize());
951}
952
953//---------------------------------------------------------------------------
954//
955// Set the resources from a TAttFill:
956//   name.FillColor  <see also SetColor>
957//   name.FillStyle  <see also SetFillStyle>
958//
959void MEnv::SetAttFill(const char *name, const TAttFill &fill)
960{
961    const TString color = Compile(name, "FillColor");
962    const TString style = Compile(name, "FillStyle");
963
964    SetColor(color, fill.GetFillColor());
965    SetFillStyle(style, fill.GetFillStyle());
966}
967
968//---------------------------------------------------------------------------
969//
970// Set the resources from a TAttMarker:
971//   name.MarkerColor  <see also SetColor>
972//   name.MarkerStyle
973//   name.MarkerSize
974//
975void MEnv::SetAttMarker(const char *name, const TAttMarker &marker)
976{
977    const TString color = Compile(name, "MarkerColor");
978    const TString style = Compile(name, "MarkerStyle");
979    const TString size  = Compile(name, "MarkerSize");
980
981    SetColor(color, marker.GetMarkerColor());
982    SetMarkerStyle(style, marker.GetMarkerStyle());
983    SetValue(size,  marker.GetMarkerSize());
984}
985
986//---------------------------------------------------------------------------
987//
988// Set the resources from a TPave:
989//   name.CornerRadius
990//   name.BorderSize
991//   name.Option
992// Also all resources from TAttLine and TAttFill are supported.
993//
994void MEnv::SetAttPave(const char *str, const TPave &pave)
995{
996    const TString name(str);
997
998    SetAttLine(name, pave);
999    SetAttFill(name, pave);
1000
1001    const TString corner = Compile(name, "CornerRadius");
1002    const TString border = Compile(name, "BorderSize");
1003    const TString option = Compile(name, "Option");
1004
1005    SetValue(corner, const_cast<TPave&>(pave).GetCornerRadius());
1006    SetValue(border, const_cast<TPave&>(pave).GetBorderSize());
1007    SetValue(option, pave.GetOption());
1008}
1009
1010//---------------------------------------------------------------------------
1011//
1012// Set the attributed for the TObject obj.
1013//
1014// There is support for:
1015//    TPave      <see SetAttPave>
1016//    TAttLine   <see SetAttLine>
1017//    TAttText   <see SetAttText>
1018//    TAttFill   <see SetAttFill>
1019//    TAttMarker <see SetAttMarker>
1020//
1021void MEnv::SetAttributes(const char *name, const TObject *obj)
1022{
1023    const TPave      *pave = dynamic_cast<const TPave*>(obj);
1024    const TAttLine   *line = dynamic_cast<const TAttLine*>(obj);
1025    const TAttText   *text = dynamic_cast<const TAttText*>(obj);
1026    const TAttFill   *fill = dynamic_cast<const TAttFill*>(obj);
1027    const TAttMarker *mark = dynamic_cast<const TAttMarker*>(obj);
1028
1029    if (pave)
1030    {
1031        SetAttPave(name, *pave);
1032        return;
1033    }
1034
1035    if (line)
1036        SetAttLine(name, *line);
1037    if (text)
1038        SetAttText(name, *text);
1039    if (fill)
1040        SetAttFill(name, *fill);
1041    if (mark)
1042        SetAttMarker(name, *mark);
1043}
1044
1045//---------------------------------------------------------------------------
1046//
1047// Add all values from TEnv env the this MEnv. To not overwrite existing
1048// values set overwrite to kFALSE
1049//
1050void MEnv::AddEnv(const TEnv &env, Bool_t overwrite)
1051{
1052    if (!GetTable() || !env.GetTable())
1053        return;
1054
1055    TIter Next(env.GetTable());
1056
1057    TEnvRec *er;
1058    while ((er = (TEnvRec*)Next()))
1059    {
1060        if (overwrite || !Defined(er->GetName()))
1061            SetValue(er->GetName(), er->GetValue(), er->GetLevel(), er->GetType());
1062    }
1063}
1064
1065//---------------------------------------------------------------------------
1066//
1067// Check MArgs for all options "--rc=" and remove them. Options should be
1068// given like
1069//
1070//    program --rc=Option1:Test1 --rc=Option2.SubOption:Test2
1071//
1072// If all resources could be interpeted corrctly kTRUE is returned. If
1073// there were problems kFALSE is returned.
1074//
1075Bool_t MEnv::TakeEnv(MArgs &arg, Bool_t print, Bool_t overwrite)
1076{
1077    if (!GetTable())
1078    {
1079        gLog << err << "ERROR - MEnv not yet initialized." << endl;
1080        return kFALSE;
1081    }
1082
1083    Bool_t ret = kTRUE;
1084    while (1)
1085    {
1086        const TString rc = arg.GetStringAndRemove("--rc=");
1087        if (rc.IsNull())
1088            break;
1089
1090        const Ssiz_t pos = rc.First(':');
1091        if (pos<0)
1092        {
1093            gLog << warn << "WARNING - Resource '" << rc << "' doesn't contain a colon... ignored." << endl;
1094            ret=kFALSE;
1095            continue;
1096        }
1097        if (pos==0)
1098        {
1099            gLog << warn << "WARNING - Resource '" << rc << "' doesn't contain a name... ignored." << endl;
1100            ret=kFALSE;
1101            continue;
1102        }
1103        if (pos==rc.Length()-1)
1104        {
1105            gLog << warn << "WARNING - Resource '" << rc << "' empty... ignored." << endl;
1106            ret=kFALSE;
1107            continue;
1108        }
1109
1110        const TString name = rc(0,     pos);
1111        const TString val  = rc(pos+1, rc.Length());
1112
1113        if (print)
1114            gLog << all << "Command line resource '" << name << "' with value '" << val << "'...";
1115
1116        const Bool_t exists = Defined(name);
1117        if (!exists)
1118        {
1119            SetValue(name, val, kEnvLocal);
1120            if (print)
1121                gLog << "set." << endl;
1122            continue;
1123        }
1124
1125        if (overwrite)
1126        {
1127            SetValue(name, "");
1128            SetValue(name, val, kEnvLocal);
1129            if (print)
1130                gLog << "changed." << endl;
1131            continue;
1132        }
1133
1134        if (print)
1135            gLog << "skipped/existing." << endl;
1136    }
1137    return ret;
1138}
1139
1140//---------------------------------------------------------------------------
1141//
1142// Add name and full path to output
1143//
1144void MEnv::PrintEnv(EEnvLevel level) const
1145{
1146    if (!TString(GetRcName()).IsNull())
1147    {
1148        cout << "# Path: " << GetRcName() << endl;
1149        cout << "# File: " << gSystem->BaseName(GetRcName()) << endl;
1150    }
1151    if (!fName.IsNull())
1152        cout << "# Name: " << fName << endl;
1153
1154    TEnv::PrintEnv(level);
1155}
1156
1157//---------------------------------------------------------------------------
1158//
1159// Print resources which have never been touched (for debugging)
1160//
1161void MEnv::PrintUntouched() const
1162{
1163    int i=0;
1164    gLog << inf << flush;
1165
1166    TString sep = "Untouched Resources in ";
1167    sep += GetRcName();
1168    gLog.Separator(sep);
1169    TIter Next(GetTable());
1170    TObject *o=0;
1171
1172    while ((o=Next()))
1173        if (!fChecked.FindObject(o->GetName()))
1174        {
1175            gLog << warn << " - Resource " << o->GetName() << " untouched" << endl;
1176            i++;
1177        }
1178    if (i==0)
1179        gLog << inf << "None." << endl;
1180    else
1181        gLog << inf << i << " resources have not been touched." << endl;
1182}
1183
1184//---------------------------------------------------------------------------
1185//
1186// Return number of resources which have not been touched.
1187//
1188Int_t MEnv::GetNumUntouched() const
1189{
1190    int i=0;
1191    TIter Next(GetTable());
1192    TObject *o=0;
1193    while ((o=Next()))
1194        if (!fChecked.FindObject(o->GetName()))
1195            i++;
1196    return i;
1197}
Note: See TracBrowser for help on using the repository browser.