ecere: Added ChangeChars(); eda/ers: ; Avoiding bad filenames
[sdk] / eda / libeda / src / ers.ec
index ace3024..878925f 100644 (file)
@@ -5,6 +5,8 @@ define margin = 36;
 
 public enum Orientation { portrait, landscape };
 
+public enum PageFormat { custom, letter, legal, ledger };
+
 public enum RenderAction { addPage, closePage, levelStart, levelFinish, groupStart, groupFinish, actualRows };
 
 static class PleaseWait : Window
@@ -30,24 +32,48 @@ public class ReportTitle : Window
    Label { this, foreground = black, anchor = { top = 4 }, labeledWindow = this };
 }
 
+static define dpi = 100;
 class PreviewPage : Window
 {
    background = dimGray;
-   //size = { 850 + shadowS + pgs * 2, 1100 + shadowS + pgs * 2 };
 
-   public property Orientation orientation
+   public property Page page
    {
       set
       {
-         if(value == portrait)
-            size = { 850 + shadowS + pgs * 2, 1100 + shadowS + pgs * 2 };
-         else if(value == landscape)
-            size = { 1100 + shadowS + pgs * 2, 850 + shadowS + pgs * 2 };
-         orientation = value;
+         page = value;
+         if(page && page.report)
+         {
+            switch(page.report.pageFormat)
+            {
+               case letter:
+                  if(page.report.orientation == landscape)
+                     size = { 11*dpi + shadowS + pgs * 2, 8.5*dpi + shadowS + pgs * 2 };
+                  else
+                     size = { 8.5*dpi + shadowS + pgs * 2, 11*dpi + shadowS + pgs * 2 };
+                  break;
+               case legal:
+                  if(page.report.orientation == landscape)
+                     size = { 14*dpi + shadowS + pgs * 2, 8.5*dpi + shadowS + pgs * 2 };
+                  else
+                     size = { 8.5*dpi + shadowS + pgs * 2, 14*dpi + shadowS + pgs * 2 };
+                  break;
+               case ledger:
+                  if(page.report.orientation == landscape)
+                     size = { 17*dpi + shadowS + pgs * 2, 11*dpi + shadowS + pgs * 2 };
+                  else
+                     size = { 11*dpi + shadowS + pgs * 2, 17*dpi + shadowS + pgs * 2 };
+                  break;
+               case custom:
+                  if(page.report.orientation == landscape && page.report.pageSize.w > page.report.pageSize.h)
+                     size = { page.report.pageSize.w + shadowS + pgs * 2, page.report.pageSize.h + shadowS + pgs * 2 };
+                  else
+                     size = { page.report.pageSize.h + shadowS + pgs * 2, page.report.pageSize.w + shadowS + pgs * 2 };
+                  break;
+            }
+         }
       }
    }
-   Orientation orientation;
-
    Page page;
 
    void OnRedraw(Surface surface)
@@ -71,30 +97,26 @@ public class Page : Window
    background = white;
 
 public:
-   property Orientation orientation
+   property Report report
    {
       set
       {
-         if(value == portrait)
+         report = value;
+         if(report)
          {
-            size = { 850, 1100 };
-            inside.size = { 850, 1100 };
+            size = report.pageSize;
+            inside.size = report.pageSize;
          }
-         else if(value == landscape)
-         {
-            size = { 1100, 850 };
-            inside.size = { 1100, 850 };
-         }
-         orientation = value;
       }
+      get { return report; }
    }
 
    Window inside { this };
 
    int headerHeight;
-   
+
 private:
-   Orientation orientation;
+   Report report;
 }
 
 public class ReportRender
@@ -156,13 +178,14 @@ public:
          ((GuiApplication)__thisModule.application).ProcessInput(true);
          pleaseWait.UpdateDisplay();
       }
-      for(pageNumber = 1; true; pageNumber++)
+      for(pageNumber = 1; ; pageNumber++)
       {
          Detail lastDetail = null;
-         page = Page { orientation = report.orientation };
+         page = Page { report = report };
          destination.AddPage(page);
          inside = page.inside;
-         inside.anchor = report.insideMarginAnchor;
+         inside.anchor = Anchor { left = report.insideMarginAnchor.left.distance, top = report.insideMarginAnchor.top.distance,
+                                  right = report.insideMarginAnchor.right.distance, bottom = report.insideMarginAnchor.bottom.distance };
          insideSize = inside.size.h;
 
          pageTop = 0;
@@ -174,10 +197,10 @@ public:
                reportHeader.anchor = Anchor { left = 0, top = 0, right = 0 };
                reportHeader.master = destination;
                reportHeader.parent = inside;
-               
+
                pageTop += reportHeader.size.h;
                reportHeader.Create();
-            
+
             }
             /*if(report.reportFooter)
             {
@@ -195,12 +218,12 @@ public:
             pageHeader.anchor = Anchor { left = 0, top = pageTop, right = 0 };
             pageHeader.master = destination;
             pageHeader.parent = inside;
-            
+
             pageTop += pageHeader.size.h;
 
             pageHeader.Create();
          }
-         
+
          if(report.pageFooter)
          {
             pageFooter = eInstance_New(report.pageFooter);
@@ -211,7 +234,7 @@ public:
          else
             footerHeight = 0;
 
-         if(report.rowDetail)
+         if(report.rowDetail || (renderAction == levelFinish && level > 0) || renderAction == groupFinish)
          {
             bool loop;
             //int levelHead = 0;
@@ -349,7 +372,7 @@ public:
 
                }
             }
-            nil = report.nil;
+            nil = report.nil && renderAction != groupFinish && (renderAction != levelFinish || level == 0);
          }
          else
          {
@@ -397,19 +420,19 @@ public:
                pageFooter.anchor = Anchor { left = 0, bottom = (int)reportFooter.size.h, right = 0 };
             else
                pageFooter.anchor = Anchor { left = 0, bottom = 0, right = 0 };
-            
+
             pageFooter.Create();
          }
          if(nil && report.reportFooter)
          {
             reportFooter.Create();
          }
-         
+
          destination.EndPage(page);
 
          if(nil)
             break;
-         
+
          // still have to bump report footer if it does not fit...
       }
       pleaseWait.Destroy(0);
@@ -445,7 +468,7 @@ private:
 
       detailSize = detail.size.h;
       overlap = (insideSize - pageTop - footerHeight) - detailSize;
-      
+
       if(overlap < 0 && detail.keepTogether)
       {
          delete detail;
@@ -472,7 +495,7 @@ private:
 public class ReportDestination : Window
 {
 public:
-   Report report;
+   public property Report report { watchable set { report = value; } get { return report; } }
 
    virtual void EndPage(Page page)
    {
@@ -483,6 +506,7 @@ public:
    virtual void AddPage(Page page);
    virtual Report GetReport() { return null; }
 private:
+   Report report;
    int pageCount;
 
    List<PreviewPage> pages { };
@@ -502,6 +526,11 @@ public class PrintedReport : ReportDestination
       return ReportDestination::OnCreate();
    }
 
+   watch(report)
+   {
+      size = report.pageSize;
+   };
+
    void AddPage(Page page)
    {
       if(pageCount && display)
@@ -537,8 +566,7 @@ public class ReportPreviewArea : ReportDestination
 
    void AddPage(Page page)
    {
-      PreviewPage previewPage { this, this, page = page, orientation = page.orientation, 
-                                   anchor = { top = pageCount * ((int)page.size.h + shadowS + pgs) } };
+      PreviewPage previewPage { this, this, page = page, anchor = { top = pageCount * ((int)page.size.h + shadowS + pgs) } };
       previewPage.Create();
       page.anchor = { left = pgs, top = pgs, right = shadowS + pgs, bottom = shadowS + pgs};
       page.master = previewPage;
@@ -546,7 +574,7 @@ public class ReportPreviewArea : ReportDestination
       page.Create();
       pageCount++;
    }
-   
+
    Report GetReport()
    {
       return report;
@@ -560,7 +588,7 @@ public class ReportPreviewArea : ReportDestination
 
 Array<FileFilter> csvFilters
 { [
-   { 
+   {
       $"Comma Separated Values Spreadsheet (*.csv)",
       "csv"
    },
@@ -573,24 +601,22 @@ public class CSVReport : ReportDestination
    hasVertScroll = true;
    dontHideScroll = true;
    background = dimGray;
-   
+
    Page lastPage;
 
    void AddPage(Page page)
    {
-      int h;
       if(pageCount && display)
          display.NextPage();
       lastPage = page;
       page.master = this;
       page.parent = this;
       page.size = { MAXINT - 10, MAXINT - 10 };
-      h = page.size.h;
       pageCount++;
       page.Create();
    }
-   
-   void PutString(File f, char * text)
+
+   void PutString(File f, const char * text)
    {
       char output[4096];
       int s = 0, d = 0;
@@ -623,6 +649,7 @@ public class CSVReport : ReportDestination
    {
       char filePath[MAX_LOCATION];
       strcpy(filePath, report.title);
+      ChangeChars(filePath, "/\\:*?\"|<>", '_');
       strcat(filePath, ".csv");
       saveTo.master = master;
       saveTo.filePath = filePath;
@@ -631,14 +658,14 @@ public class CSVReport : ReportDestination
          File f = FileOpen(saveTo.filePath, write);
          if(f)
          {
-            Detail detail, first = null;         
+            Detail detail, first = null;
             for(detail = (Detail)page.inside.firstChild; detail && detail != first; detail = (Detail)detail.next)
             {
                if(!first) first = detail;
                if(eClass_IsDerived(detail._class, class(Detail)))
                {
                   Label label, first = null;
-      
+
                   if(detail._class == report.pageFooter) continue;
                   if(detail._class == report.groupings[0].header)
                      f.Puts("\n");
@@ -647,7 +674,7 @@ public class CSVReport : ReportDestination
                      if(!first) first = label;
                      if(label._class == class(ReportTitle) || eClass_IsDerived(label._class, class(Label)))
                      {
-                        char * text = label.text;
+                        const char * text = label.text;
                         if(label != first)f.Puts(",");
                         if(text)
                            PutString(f, text);
@@ -675,7 +702,7 @@ public class IdFilter : struct
 public:
    Id id;
    Field field;
-   
+
    bool RowMatch(Row row)
    {
       Id value;
@@ -716,7 +743,7 @@ public:
       filters.Free();
       delete row;
    }
-   
+
    virtual bool ShouldSkip()
    {
       return false;
@@ -738,7 +765,7 @@ public:
          result = row.Next();
       if(!result)
          return false;
-      
+
       if(reverseLink)
          reverseLink.row.GetData(reverseListFieldLink, reverseIdList);
 
@@ -826,12 +853,15 @@ public:
 public class Report
 {
 public:
-   Orientation orientation;
+   public property Orientation orientation { set { orientation = value; UpdateSize(); } get { return orientation; } }
+   public property PageFormat pageFormat { set { pageFormat = value; UpdateSize(); } get { return pageFormat; } }
+
+   Size pageSize;
    Anchor insideMarginAnchor;
 
    Array<Grouping> groupings { };
 
-   property String title
+   property const String title
    {
       set
       {
@@ -856,7 +886,7 @@ public:
    {
       return grouping.Advance(linkId, dontAdvance);
    }
-   
+
    virtual bool ExecuteData(Database db)
    {
       return false;
@@ -875,6 +905,40 @@ public:
       }
    }
 
+private:
+   Orientation orientation;
+   PageFormat pageFormat;
+
+   void UpdateSize()
+   {
+      switch(pageFormat)
+      {
+         case letter:
+            if(orientation == landscape)
+               pageSize = { 11*dpi, 8.5*dpi };
+            else
+               pageSize = { 8.5*dpi, 11*dpi };
+            break;
+         case legal:
+            if(orientation == landscape)
+               pageSize = { 14*dpi, 8.5*dpi };
+            else
+               pageSize = { 8.5*dpi, 14*dpi };
+            break;
+         case ledger:
+            if(orientation == landscape)
+               pageSize = { 17*dpi, 11*dpi };
+            else
+               pageSize = { 11*dpi, 17*dpi };
+            break;
+      }
+   }
+
+   Report()
+   {
+      property::pageFormat = letter;
+   }
+
    ~Report()
    {
       groupings.Free();