<\s]+#{@search_regx}[^>]+?>|#{@search_regx})/mi,%{\\1 }))
+                  : c['body']
+                  %{ocn #{c['ocn']}  : 
#{matched_para}}
+                elsif c['suffix'] =~/1/ #doc
+                  %{#{title}ocn #{c['ocn']}:#{c['body']}}
+                end
+                @counter_txt_ocn+=1
+                output=title+text
+              else #elsif cgi['view']=~/index/                                #% idx body
+                if c['suffix'] !~/1/ #seg
+                  index=%{#{c['ocn']} , } if @text_search_flag
+                elsif c['suffix'] =~/1/ #doc #FIX
+                  index=%{#{c['ocn']} , }
+                end
+                if c['seg'] =~/\S+/
+                  if @text_search_flag
+                    @counter_txt_ocn+=1
+                    output=title+index
+                  end
+                else
+                  @counter_txt_ocn+=1
+                  output=c['suffix'] !~/1/ \
+                  ? title+index
+                  : %{#{title}#{c['ocn'].sort}, }
+                end
+              end
+            else output=title
+            end
+            @counters_txt=if @counter_txt_doc > 0
+              if checked_stats =~/\S/
+                @@lt_t=(@counter_txt_ocn==dbi_statement.sql_match_limit.to_i) ? true : false
+                start=(@@offset.to_i+1).to_s
+                range=(@@offset.to_i+@counter_txt_ocn.to_i).to_s
+                %{Found #{@counter_txt_ocn} times in the main body of #{@counter_txt_doc} documents [ matches #{start} to #{range} ]  }
+              else ''
+              end
+            else ''
+            end
+            @body_main << output #+ details
+          end
+          oldtid = 0
+          offset=dbi_statement.sql_offset.to_s
+          limit=dbi_statement.sql_match_limit.to_s
+          @@lt_t ||=false; @@lt_e ||=false
+          canned=(@@lt_t or @@lt_e) \
+          ? dbi_statement.pre_next(true,@image_src).to_s
+          : dbi_statement.pre_next(false,@image_src).to_s
+          limit=dbi_statement.sql_match_limit.to_s
+          cgi.out{@header.force_encoding("UTF-8") + @counters_txt.force_encoding("UTF-8") + @counters_endn.force_encoding("UTF-8") + canned.force_encoding("UTF-8") + @body_main.force_encoding("UTF-8") + canned.force_encoding("UTF-8") + @tail.force_encoding("UTF-8")} #% print cgi_output_header+counters+body
+        end
+        rescue Exception => e
+          s='' + CGI::escapeHTML(e.backtrace.reverse.join("\n"))
+          s << CGI::escapeHTML(e.message) + ' '
+          cgi.out{s}
+          next
+        ensure # eg. disconnect from server
+          @conn.disconnect if @conn
+        end
+      end
+      WOK_SQL
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* document header
+
+#+NAME: sisu_document_header
+#+BEGIN_SRC text
+encoding: utf-8
+- Name: SiSU
+
+  - Description: documents, structuring, processing, publishing, search
+    cgi
+
+  - Author: Ralph Amissah
+    
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+    All Rights Reserved.
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/config.org b/org/config.org
new file mode 100644
index 00000000..b44d9792
--- /dev/null
+++ b/org/config.org
@@ -0,0 +1,310 @@
+-*- mode: org -*-
+#+TITLE:       sisu configure site
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:config:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* conf.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/conf.rb"
+# <>
+module SiSU_Initialize
+  require_relative 'se'                                 # se.rb
+    include SiSU_Env
+    include SiSU_Screen
+  require_relative 'relaxng'                            # relaxng.rb
+    include SiSU_Relaxng
+  require_relative 'css'                                # css.rb
+    include SiSU_Style
+  class Source
+    def initialize(opt)
+      @opt=opt
+    end
+    def read
+      ConfigSite.new(@opt).make_homepage
+      ConfigSite.new(@opt).css
+      ConfigSite.new(@opt).dtd
+      ConfigSite.new(@opt).cp_local_images
+      ConfigSite.new(@opt).cp_external_images
+      ConfigSite.new(@opt).cp_webserver_images
+    end
+  end
+  class ConfigSite #config files such as css are not updated if they already exist unless forced using the --init=site modifier
+    require_relative 'se'                               # se.rb
+    def initialize(opt)
+      @opt=opt
+      @env=SiSU_Env::InfoEnv.new(@opt.fns)
+      @suffix={
+        rnc: 'rnc',
+        rng: 'rng',
+        xsd: 'xsd',
+      }
+      @path={
+        xml: @env.path.output + '/_sisu/xml',
+        xsd: @env.path.output + '/_sisu/xml/xsd',
+        rnc: @env.path.output + '/_sisu/xml/rnc',
+        rng: @env.path.output + '/_sisu/xml/rng',
+        style: @env.path.output + '/' + @env.path.style,
+      }
+      @pwd,@home=Dir.pwd,@env.path.home
+    end
+    def make_homepage
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Make homepage',
+        ''
+      ).colorize unless @opt.act[:quiet][:set]==:on
+      SiSU_Env::CreateSite.new(@opt).homepage
+    end
+    def cp_local_images
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Copy images',
+        ''
+      ).colorize unless @opt.act[:quiet][:set]==:on
+      SiSU_Env::CreateSite.new(@opt).cp_local_images
+      SiSU_Env::CreateSite.new(@opt).cp_webserver_images_local #this should not have been necessary
+      SiSU_Env::CreateSite.new(@opt).cp_base_images #base images (nav etc.) used by all html
+    end
+    def cp_external_images
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Copy external images',
+        ''
+      ).colorize if @opt.act[:verbose_plus][:set]==:on
+      SiSU_Env::CreateSite.new(@opt).cp_external_images
+    end
+    def cp_webserver_images
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Copy webserver/output file images',
+        ''
+      ).colorize unless @opt.act[:quiet][:set]==:on
+      SiSU_Env::CreateSite.new(@opt).cp_webserver_images
+    end
+    def css
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Configuring CSSs',
+        ''
+      ).colorize unless @opt.act[:quiet][:set]==:on
+      SiSU_Env::CreateSite.new(@opt).cp_css
+    end
+    def dtd
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'invert',
+        'Configuring DTDs',
+        ''
+      ).colorize unless @opt.act[:quiet][:set]==:on
+      @rxng=SiSU_Relaxng::RelaxNG.new
+      @path.each { |d| FileUtils::mkdir_p(d[1]) \
+      unless FileTest.directory?(d[1]) }
+      #ugly code, sort later
+      if @rxng.methods.join =~/[^_]dtd_sax\b/
+        if @rxng.dtd_sax.length > 200
+          dtd=File.new("#{@path[:style]}/#{@rxng.rng_name.output_sax}",'w')
+          dtd << @rxng.dtd_sax
+          dtd.close
+        else trang_rnc_model_output_sax
+        end
+      else trang_rnc_model_output_sax
+      end
+      if @rxng.methods.join =~/[^_]dtd_dom\b/
+        if @rxng.dtd_dom.length > 200
+          dtd=File.new("#{@path[:style]}/#{@rxng.rng_name.output_dom}",'w')
+          dtd << @rxng.dtd_dom
+          dtd.close
+        else trang_rnc_model_output_dom
+        end
+      else trang_rnc_model_output_dom
+      end
+      if @rxng.methods.join =~/[^_]dtd_node\b/
+        if @rxng.dtd_node.length > 200
+          dtd=File.new("#{@path[:style]}/#{@rxng.rng_name.input_node}",'w')
+          dtd << @rxng.dtd_node
+          dtd.close
+        else trang_rnc_model_input_node
+        end
+      else trang_rnc_model_input_node
+      end
+      if @rxng.methods.join =~/[^_]dtd_xhtml\b/
+        if @rxng.dtd_xhtml.length > 200
+          dtd=File.new("#{@path[:style]}/#{@rxng.rng_name.output_xhtml}",'w')
+          dtd << @rxng.dtd_xhtml
+          dtd.close
+        else trang_rnc_model_output_xhtml
+        end
+      else trang_rnc_model_output_xhtml
+      end
+    end
+    def trang_rnc_model_output_sax
+      s=@suffix
+      rnc_src=@env.processing_path.ao + '/sax.' + s[:rnc]
+      rnc_file=@path[:rnc] + '/' + @rxng.rnc_name.output_sax
+      rng_file=@path[:rng] + '/' + @rxng.rng_name.output_sax
+      xsd_file=@path[:xsd] + '/' + @rxng.xsd_name.output_sax
+      rnc=File.new(rnc_src,'w')
+      rnc << @rxng.rnc_model_output_sax
+      rnc.close
+      #xsd
+      schema=SiSU_Env::SystemCall.new(rnc_src,xsd_file)
+      schema.relaxng(@opt.selections.str)
+      #rng
+      schema=SiSU_Env::SystemCall.new(rnc_src,rng_file)
+      schema.relaxng(@opt.selections.str)
+      #rnc
+      if FileTest.file?(rnc_src)
+        FileUtils::cp(rnc_src,rnc_file)
+        FileUtils::chmod(0644,rnc_file)
+      else STDERR.puts %{\t*WARN* did not find rnc - "#{rnc_src}" [#{__FILE__}:#{__LINE__}]}
+      end
+    end
+    def trang_rnc_model_output_dom
+      s=@suffix
+      rnc_src=@env.processing_path.ao + '/dom.' + s[:rnc]
+      rnc_file=@path[:rnc] + '/' + @rxng.rnc_name.output_dom
+      rng_file=@path[:rng] + '/' + @rxng.rng_name.output_dom
+      xsd_file=@path[:xsd] + '/' + @rxng.xsd_name.output_dom
+      rnc=File.new(rnc_src,'w')
+      rnc << @rxng.rnc_model_output_dom
+      rnc.close
+      #xsd
+      schema=SiSU_Env::SystemCall.new(rnc_src,xsd_file)
+      schema.relaxng(@opt.selections.str)
+      #rng
+      schema=SiSU_Env::SystemCall.new(rnc_src,rng_file)
+      schema.relaxng(@opt.selections.str)
+      #rnc
+      if FileTest.file?(rnc_src)
+        FileUtils::cp(rnc_src,rnc_file)
+        FileUtils::chmod(0644,rnc_file)
+      else STDERR.puts %{\t*WARN* did not find rnc - "#{rnc_src}" [#{__FILE__}:#{__LINE__}]}
+      end
+    end
+    def trang_rnc_model_output_xhtml
+      s=@suffix
+      rnc_src=@env.processing_path.ao + '/xhtml.' + s[:rnc]
+      rnc_file=@path[:rnc] + '/' + @rxng.rnc_name.output_xhtml
+      rng_file=@path[:rng] + '/' + @rxng.rng_name.output_xhtml
+      xsd_file=@path[:xsd] + '/' + @rxng.xsd_name.output_xhtml
+      rnc=File.new(rnc_src,'w')
+      rnc << @rxng.rnc_model_output_xhtml
+      rnc.close
+      #xsd
+      schema=SiSU_Env::SystemCall.new(rnc_src,xsd_file)
+      schema.relaxng(@opt.selections.str)
+      #rng
+      schema=SiSU_Env::SystemCall.new(rnc_src,rng_file)
+      schema.relaxng(@opt.selections.str)
+      #rnc
+      if FileTest.file?(rnc_src)
+        FileUtils::cp(rnc_src,rnc_file)
+        FileUtils::chmod(0644,rnc_file)
+      else STDERR.puts %{\t*WARN* did not find rnc - "#{rnc_src}" [#{__FILE__}:#{__LINE__}]}
+      end
+    end
+    def trang_rnc_model_input_sax
+      rnc_file=@env.processing_path.ao + '/sax.rnc'
+      dtd_file=@path[:xsd] + '/' + @rxng.rng_name.input_sax
+      rnc=File.new(rnc_file,'w')
+      rnc << @rxng.rnc_model_output_sax
+      rnc.close
+      schema=SiSU_Env::SystemCall.new(rnc_file,dtd_file)
+      schema.relaxng(@opt.selections.str)
+    end
+    def trang_rnc_model_input_dom
+      rnc_file=@env.processing_path.ao + '/dom.rnc'
+      dtd_file=@path[:xsd] + '/' + @rxng.rng_name.input_dom
+      rnc=File.new(rnc_file,'w')
+      rnc << @rxng.rnc_model_output_dom
+      rnc.close
+      schema=SiSU_Env::SystemCall.new(rnc_file,dtd_file)
+      schema.relaxng(@opt.selections.str)
+    end
+    def trang_rnc_model_input_node
+      rnc_file=@env.processing_path.ao + '/node.rnc'
+      dtd_file=@path[:xsd] + '/' + @rxng.rng_name.input_node
+      rnc=File.new(rnc_file,'w')
+      rnc << @rxng.rnc_model_input_node
+      rnc.close
+      schema=SiSU_Env::SystemCall.new(rnc_file,dtd_file)
+      schema.relaxng(@opt.selections.str)
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* document header
+
+#+NAME: sisu_document_header
+#+BEGIN_SRC text
+encoding: utf-8
+- Name: SiSU
+
+  - Description: documents, structuring, processing, publishing, search
+    config
+
+  - Author: Ralph Amissah
+    
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/css.org b/org/css.org
new file mode 100644
index 00000000..266c0051
--- /dev/null
+++ b/org/css.org
@@ -0,0 +1,3508 @@
+-*- mode: org -*-
+#+TITLE:       sisu css
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:css:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* css.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/css.rb"
+# <>
+module SiSU_Style
+  require_relative 'se'                                 # se.rb
+  require_relative 'html_parts'                         # html_parts.rb
+  class CSS_HeadInfo
+    def initialize(md,ft='html')
+      @md,@ft=md,ft
+      @env=SiSU_Env::InfoEnv.new('',md)
+      @fn_css ||=SiSU_Env::CSS_Default.new
+      @o_str ||=SiSU_Env::ProcessingSettings.new(md).output_dir_structure
+      css_copy
+    end
+    def stylesheet
+      def css_path
+        SiSU_Env::CSS_Stylesheet.new(@md)
+      end
+      def css_embed_content
+        @css_embed_content ||=SiSU_Style::CSS.new
+      end
+      def css_embed?
+        if @ft=='html' \
+        && @o_str.dump_or_redirect?
+          true
+        else
+          false
+        end
+      end
+      def css_embed(css)
+        <<-WOK
+          
+        WOK
+      end
+      def css_action
+        css=case @ft
+        when 'html'
+          css=css_embed_content.html
+          css_embed(css)
+        when 'xhtml'
+          css_path.xhtml
+        when 'xml_sax'
+          css_path.xml_sax
+        when 'xml_dom'
+          css_path.xml_dom
+        when 'xml_docbook'
+          css_path.xml_docbook
+        else
+          css_embed_content.html
+        end
+      end
+      def css_head
+        (css_embed?) \
+        ? css_action
+        : "#{css_path.html}#{css_path.html_seg}"
+      end
+      def css_head_seg
+        (css_embed?) \
+        ? css_action
+        : css_path.html_seg
+      end
+      def css_head_xml
+        css_action
+      end
+      self
+    end
+    def css_copy
+      if @o_str.dump_or_redirect?
+        css=SiSU_Style::CSS.new
+        if @o_str.dump?
+          css_pth="#{@md.opt.opt_act[:dump][:inst]}/#{@env.path.style}"
+        elsif @o_str.redirect?
+          css_pth="#{@md.opt.opt_act[:redirect][:inst]}/#{@md.fnb}/#{@env.path.style}"
+        end
+        FileUtils::mkdir_p(css_pth) unless FileTest.directory?(css_pth)
+        case @ft
+        when 'html'
+          style=File.new("#{css_pth}/#{@fn_css.html}",'w')
+          style << css.html
+          style.close
+        when 'xhtml'
+          style=File.new("#{css_pth}/#{@fn_css.xhtml}",'w')
+          style << css.xhtml
+          style.close
+        when 'xml_sax'
+          style=File.new("#{css_pth}/#{@fn_css.xml_sax}",'w')
+          style << css.xml_sax
+          style.close
+        when 'xml_dom'
+          style=File.new("#{css_pth}/#{@fn_css.xml_dom}",'w')
+          style << css.xml_dom
+          style.close
+          css_path.xml_dom
+        when 'xml_docbook'
+          style=File.new("#{css_pth}/#{@fn_css.xml_docbook}",'w')
+          style << css.xml_docbook
+          style.close
+          css_path.xml_docbook
+        end
+      end
+    end
+  end
+  class CSS
+    include SiSU_Parts_HTML
+    def fonts
+      the_font.set_fonts
+    end
+    def html_tables                               #stylesheet for css table_pages
+<
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+    All Rights Reserved.
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/db.org b/org/db.org
new file mode 100644
index 00000000..4a2f216b
--- /dev/null
+++ b/org/db.org
@@ -0,0 +1,4808 @@
+-*- mode: org -*-
+#+TITLE:       sisu db sql
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:db:sql:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* dbi.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/dbi.rb"
+# <>
+module  SiSU_DBI                                                                 #% database building
+  require_relative 'se'                                 # se.rb
+    include SiSU_Env; include SiSU_Screen
+  require_relative 'dp'                                 # dp.rb
+    include SiSU_Param
+  require_relative 'db_dbi'                             # db_dbi.rb
+    include SiSU_DbDBI
+  require_relative 'html_lite_shared'                   # html_lite_shared.rb
+    include SiSU_FormatShared
+  class SQL
+    def initialize(opt)
+      @opt=opt
+      @db=SiSU_Env::InfoDb.new
+      if @opt.act[:psql][:set]==:on \
+      or @opt.act[:sqlite][:set]==:on
+        @sql_type=if @opt.act[:psql][:set]==:on
+          maintenance_check(@opt,__FILE__,__LINE__) if @opt.act[:maintenance][:set]==:on
+          :pg
+        elsif @opt.act[:psql][:set]==:on
+          maintenance_check(@opt,__FILE__,__LINE__) if @opt.act[:maintenance][:set]==:on
+          :pg
+        elsif @opt.act[:sqlite][:set]==:on
+          maintenance_check(@opt,__FILE__,__LINE__) if @opt.act[:maintenance][:set]==:on
+          :sqlite
+        elsif @opt.act[:sqlite][:set]==:on
+          maintenance_check(@opt,__FILE__,__LINE__) if @opt.act[:maintenance][:set]==:on
+          :sqlite
+        else
+          maintenance_check(@opt,__FILE__,__LINE__) if @opt.act[:maintenance][:set]==:on
+          :sqlite
+        end
+        if    @sql_type==:pg    then SiSU_Env::Load.new('pg',true).prog
+        elsif @sql_type==:sqlite then SiSU_Env::Load.new('sqlite3',true).prog
+        end
+      end
+    end
+    def maintenance_check(opt,file,line)
+      p opt.selections.str
+      p "at #{file} #{line}"
+    end
+    def read_psql
+      begin
+        begin
+          require 'pg'
+        rescue LoadError
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+            error('pg NOT FOUND (LoadError)')
+        end
+        @conn=@db.psql.conn_pg
+      rescue
+        if @opt.act[:psql_create][:set]==:on
+          cX=SiSU_Screen::Ansi.new(@opt.act[:color_state][:set]).cX
+          puts <<-WOK
+manually create the database: "#{cX.green}#{@db.db}#{cX.off}" if it does not yet exist
+  #{cX.yellow}createdb #{@db.db}#{cX.off}
+          WOK
+          #sudo su -p postgres;  createdb #{@db.db}; #[createuser?]
+        end
+      ensure
+      end
+    end
+    def read_sqlite
+      begin
+        begin
+          begin
+            require 'sqlite3'
+          rescue LoadError
+            SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+              error('sqlite3 NOT FOUND (LoadError)')
+          end
+          @conn=@db.sqlite.conn_sqlite3
+        rescue LoadError
+          errmsg='sqlite3 NOT FOUND (LoadError)'
+          if @opt.act[:no_stop][:set]==:on
+            SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+              error(errmsg + ', ' + 'attempt to proceed without sqlite output (as requested)')
+          else
+            SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+              error(errmsg + ', ' + 'STOPPING')
+            exit
+          end
+        end
+      end
+    end
+    def connect
+      case @sql_type
+      when :pg     then read_psql #read_pg
+      when :sqlite then read_sqlite
+      end
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        "SQL DB #{@sql_type.upcase}",
+        @opt.fno
+      ).dbi_title unless @opt.act[:quiet][:set]==:on
+      begin
+        SiSU_DbDBI::Case.new(@opt,@conn,@sql_type).cases
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,@cf,@opt.fns).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+      begin
+      rescue
+        connect
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* dbi_discrete.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/dbi_discrete.rb"
+# <>
+module  SiSU_DBI_Discrete                               #% database building
+  require_relative 'se'                                 # se.rb
+    include SiSU_Env; include SiSU_Screen
+  require_relative 'dp'                                 # dp.rb
+    include SiSU_Param
+  require_relative 'db_dbi'                             # db_dbi.rb
+    include SiSU_DbDBI
+  require_relative 'html_lite_shared'                   # html_lite_shared.rb
+    include SiSU_FormatShared
+  begin
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('fileutils NOT FOUND (LoadError)')
+  end
+  class SQL
+    def initialize(opt)
+      SiSU_Env::Load.new('sqlite3',true).prog
+      @opt=opt
+      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
+      @md=@particulars.md
+      if @opt.act[:sqlite][:set]==:on
+        @sql_type=:sqlite
+        if @opt.act[:maintenance][:set]==:on
+          maintenance_check(@opt,__FILE__,__LINE__)
+        end
+      end
+      @output_path=@md.file.output_path.sqlite_discrete.dir
+      @filename=@md.file.base_filename.sqlite_discrete
+      @file_maint=sql_maintenance_file
+      @file="#{@output_path}/#{@filename}"
+    end
+    def build
+      prepare
+      create_and_populate
+    end
+    def maintenance_check(opt,file,line)
+      #p opt.selections.str
+      p "at #{file} #{line}"
+    end
+    def prepare
+      if not FileTest.directory?(@output_path)
+        FileUtils::mkdir_p(@output_path)
+      elsif @file
+        FileUtils::rm_rf(@file)
+      end
+    end
+    def db_exist?(db,conn)
+      msg=%{no connection with sqlite database established, createdb "#{db.sqlite.db}"?}
+      if (not (FileTest.file?(db.sqlite.db)) \
+      or FileTest.zero?(db.sqlite.db))
+        puts msg
+        exit
+      end
+      if conn.is_a?(NilClass)
+        puts msg
+        exit
+      end
+    end
+    def create_and_populate
+      db=SiSU_Env::DbOp.new(@md)
+      conn=db.sqlite_discrete.conn_sqlite3
+      sdb=SiSU_DbDBI::Create.new(@opt,conn,@file,:sqlite)
+      sdb_index=SiSU_DbDBI::Index.new(@opt,conn,@file,:sqlite)
+      sdb.output_dir?
+      begin
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          'SQLite (discrete)',
+          "[#{@opt.f_pth[:lng_is]}] #{@opt.fno}"
+        ).green_title_hi unless @opt.act[:quiet][:set]==:on
+        sdb.create_db
+        sdb.create_table.metadata_and_text
+        sdb.create_table.doc_objects
+        sdb.create_table.endnotes
+        sdb.create_table.endnotes_asterisk
+        sdb.create_table.endnotes_plus
+        sdb.create_table.urls
+        sdb_index.create_indexes
+        db_exist?(db,conn)
+        sdb_import=SiSU_DbDBI::Import.new(@opt,conn,@file_maint,:sqlite)
+        sdb_import.marshal_load
+        tell=SiSU_Screen::Ansi.new(
+               @opt.act[:color_state][:set],
+               "sqlite3 #{db.sqlite.db} database?"
+             )
+        tell.puts_grey if @opt.act[:verbose][:set]==:on
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,'-d').location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+        sdb.output_dir?
+      end
+    end
+    def read_sqlite
+      begin
+        begin
+          require 'sqlite3'
+          @conn=@db.sqlite.conn_sqlite3
+        rescue LoadError
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).error('sqlite3 not available')
+        ensure
+          Dir.chdir(@opt.f_pth[:pth])
+        end
+      end
+    end
+    def connect
+      begin
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "DBI (#{@sql_type}) #{@opt.selections.str}",
+          @opt.fns
+        ).dbi_title unless @opt.act[:quiet][:set]==:on
+        @db.sqlite_discrete.conn_sqlite3
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,@cf,@opt.fns).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def populate
+    end
+    def sql_maintenance_file
+      file=if @opt.act[:maintenance][:set]==:on
+        if @opt.fns and not @opt.fns.empty?
+          @env=SiSU_Env::InfoEnv.new(@opt.fns) if @opt.fns
+          if @sql_type ==:sqlite
+            puts "\n#{@env.processing_path.sqlite}/#{@opt.fns}.sql"
+          end
+          @db=SiSU_Env::InfoDb.new
+          @job="sqlite3 #{@db.sqlite.db} < #{@env.processing_path.sqlite}/#{@opt.fns}.sql"
+          if @sql_type ==:sqlite
+            File.new("#{@env.processing_path.sqlite}/#{@opt.fns}.sql",'w+')
+          else
+            File.new("#{@env.processing_path.postgresql}/#{@opt.fns}.sql",'w+')
+          end
+        elsif @opt.fns \
+        and @opt.fns.inspect =~/create/
+          nil #sort variations later
+        else nil
+        end
+      else nil
+      end
+      file
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* db_dbi.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_dbi.rb"
+# <>
+module  SiSU_DbDBI
+  require_relative 'db_columns'                                             # db_columns.rb
+  require_relative 'db_tests'                                               # db_tests.rb
+  require_relative 'db_create'                                              # db_create.rb
+  require_relative 'db_select'                                              # db_select.rb
+  require_relative 'db_indexes'                                             # db_indexes.rb
+  require_relative 'db_drop'                                                # db_drop.rb
+  require_relative 'db_remove'                                              # db_remove.rb
+  require_relative 'db_load_tuple'                                          # db_load_tuple.rb
+  require_relative 'db_import'                                              # db_import.rb
+  class ColumnSize < SiSU_DbColumns::ColumnSize                             # db_columns.rb
+  end
+  class Test < SiSU_DbTests::Test                                           # db_tests.rb
+  end
+  class Create >
+module SiSU_DbText
+  class Prepare
+    def special_character_escape(str)
+      str=str.to_s.gsub(/'/m,"''"). #string.gsub!(/'/,"\047") #string.gsub!(/'/,"\\'")
+        gsub(/(\\)/m,'\1\1'). #ok but with warnings, double backslash on sqlite #str.gsub!(/[\\]/m,'\\x5C') #ok but with warnings, but not for sqlite #str.gsub!(/(\\)/m,'\1') #ok for sqlite not for pgsql
+        gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/m," \n").
+        gsub(/#{Mx[:tag_o]}\S+?#{Mx[:tag_c]}/m,''). #check
+        gsub(/#{Mx[:lnk_o]}\s*(\S+?\.(?:png|jpg))(?:\s+\d+x\d+)?(.+?)#{Mx[:lnk_c]}\S+/m,'[image: \1] \2').
+        gsub(/#{Mx[:lnk_o]}\s*(.+?)\s*#{Mx[:lnk_c]}(?:file|ftp):\/\/\S+?([.,!?]?(?:\s|$))/m,'\1\2').
+        gsub(/#{Mx[:lnk_o]}\s*(.+?)\s*#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/m,'\1')
+    end
+    def clean_searchable_text_from_document_objects(arr)
+      en=[]
+      arr=(arr.is_a?(String)) ? [ arr ] : arr
+      txt_arr=arr.each.map do |s|
+        s=s.gsub(/#{Mx[:fa_o]}[a-z]{1,4}#{Mx[:fa_o_c]}/m,'').
+            gsub(/#{Mx[:fa_c_o]}[a-z]{1,4}#{Mx[:fa_c]}/m,'').
+            gsub(/ /m,' ')
+        en << s.scan(/#{Mx[:en_a_o]}\s*(.+?)\s*#{Mx[:en_a_c]}/m)
+        s=s.gsub(/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/m,'').
+          gsub(/#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]}/m,'').
+          gsub(/ \s+/m,' ')
+        #p s if s =~/[^ \nA-Za-z0-9'"`?!#@$%^&*=+,.;:\[\]()<>{}‹›|\\\/~_-]/
+        s
+      end
+      txt_arr=txt_arr << en
+      txt=txt_arr.flatten.join("\n")
+      special_character_escape(txt)
+    end
+    def clean_document_objects_body(arr)
+      en=[]
+      arr=(arr.is_a?(String)) ? [ arr ] : arr
+      txt_arr=arr.each.map do |s|
+        en << s.scan(/#{Mx[:en_a_o]}\s*(.+?)\s*#{Mx[:en_a_c]}/m)
+        s=s.
+          gsub(/#{Mx[:en_a_o]}\s*(\d+).+?#{Mx[:en_a_c]}/m,
+            '\1 ').
+          gsub(/#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]}/m,'').
+          gsub(/ \s+/m,' ')
+        s
+      end
+      en_arr=en.flatten.each.map do |e|
+        e.sub(/^(\d+)\s*/,'\1  ')
+      end
+      txt_arr=txt_arr << en_arr
+      txt=txt_arr.flatten.join("\n ")
+      special_character_escape(txt)
+    end
+    def clean_searchable_text_from_document_source(arr)
+      txt_arr,en=[],[]
+      arr=(arr.is_a?(String)) ? arr.split(/\n+/m) : arr
+      arr.each do |s|
+        s=s.gsub(/([*\/_-])\{(.+?)\}\1/m,'\2').
+          gsub(/^(?:block|group|poem|code)\{/m,'').
+          gsub(/^\}(?:block|group|poem|code)/m,'').
+          gsub(/\A(?:@\S+:\s+.+)\Z/m,'')
+        if s =~/^:A~/
+          if defined? @md.creator \
+          and defined? @md.creator.author \
+          and not @md.creator.author.empty?
+            s=s.gsub(/@author/,@md.creator.author)
+          else
+            SiSU_Screen::Ansi.new(
+              'v',
+              'WARNING Document Author information missing; provide @creator: :author:',
+              @md.fnb
+            ).warn unless @md.opt.act[:quiet][:set]==:on
+          end
+          if defined? @md.title \
+          and defined? @md.title.full \
+          and not @md.title.full.empty?
+            s=s.gsub(/@title/,@md.title.full)
+          else
+            SiSU_Screen::Ansi.new(
+              'v',
+              'WARNING Document Title missing; provide @title:',
+              @md.fnb
+            ).warn unless @md.opt.act[:quiet][:set]==:on
+          end
+        end
+        s=s.gsub(/^(?:_[1-9]\*?|_\*)\s+/m,'').
+          gsub(/^(?:[1-9]\~(\S+)?)\s+/m,'').
+          gsub(/^(?::?[A-C]\~(\S+)?)\s+/m,'').
+          gsub(/^%{1,3} .+/m,''). #removed even if contained in code block
+          gsub(/ /m,' ')
+        #en << s.scan(/~\{\s*(.+?)\s*\}~/m)
+        s=s.gsub(/~\{.+?\}~/m,'').
+          gsub(/ \s+/m,' ')
+        ##special_character_escape(s)
+        #p s if s =~/[^ \nA-Za-z0-9'"`?!#@$%^&*=+,.;:\[\]()<>{}‹›|\\\/~_-]/
+        s
+      end
+      txt_arr << arr << en
+      txt=txt_arr.flatten.join("\n")
+      txt=special_character_escape(txt)
+      txt
+    end
+    def strip_markup(str) #define rules, make same as in dal clean
+      str=str.gsub(/#{Mx[:fa_superscript_o]}(\d+)#{Mx[:fa_superscript_c]}/,'[\1]').
+        gsub(/(?: \\;|#{Mx[:nbsp]})+/,' ').
+        gsub(/#{Mx[:tc_o]}#{Mx[:tc_p]}#{Mx[:tc_p]}\d+(.+)#{Mx[:tc_c]}/u,'\1').         #tables
+        gsub(/#{Mx[:tc_p]}#{Mx[:tc_p]}\d+#{Mx[:tc_p]}/u,' ').                          #tables
+        gsub(/#{Mx[:tc_p]}/u,' ').                                                     #tables tidy later
+        gsub(/<.+?>/,'').
+        gsub(/#{Mx[:lnk_o]}.+?\.(?:png|jpg|gif).+?#{Mx[:lnk_c]}(?:file|ftp)\/\/:\S+ /,' [image] '). # else image names found in search
+        gsub(/#{Mx[:lnk_o]}.+?\.(?:png|jpg|gif).+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,' [image]'). # else image names found in search
+        gsub(/\s\s+/,' ').
+        strip
+    end
+    def unique_words(str)
+      a=str.scan(/[a-zA-Z0-9\\\/_-]{2,}/) #a=str.scan(/\S+{2,}/)
+      str=a.uniq.sort.join(' ')
+      str
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* create drop import remove
+** db_create.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_create.rb"
+# <>
+module SiSU_DbCreate
+  require_relative 'db_columns'                         # db_columns.rb
+  class Create < SiSU_DbColumns::Columns
+    require_relative 'se'                               # se.rb
+    @@dl=nil
+    def initialize(opt,conn,file,sql_type=:pg)
+      @opt,@conn,@file,@sql_type=opt,conn,file,sql_type
+      @cX=SiSU_Screen::Ansi.new(@opt.act[:color_state][:set]).cX
+      @comment=(@sql_type==:pg) \
+      ? (SiSU_DbCreate::Comment.new(@conn,@sql_type))
+      : nil
+      @@dl ||=SiSU_Env::InfoEnv.new.digest.length
+    end
+    def available
+      DBI.available_drivers.each do |driver|
+        puts "Driver: #{driver}"
+        DBI.data_sources(driver).each do |dsn|
+          puts "\tDatasource: #{dsn}"
+        end
+      end
+    end
+    def create_db
+      @env=SiSU_Env::InfoEnv.new(@opt.fns)
+      tell=(@sql_type==:sqlite) \
+      ? SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          'Create SQLite db tables in:',
+          %{"#{@file}"}
+        )
+      : SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          'Create pgSQL db tables in:',
+          %{"#{Db[:name_prefix]}#{@env.path.base_markup_dir_stub}"}
+        )
+      if (@opt.act[:verbose][:set]==:on \
+      || @opt.act[:verbose_plus][:set]==:on \
+      || @opt.act[:maintenance][:set]==:on)
+        tell.dark_grey_title_hi
+      end
+      SiSU_Env::SystemCall.new.create_pg_db(@env.path.base_markup_dir_stub) if @sql_type==:pg #watch use of path.base_markup_dir_stub instead of stub
+    end
+    def output_dir?
+      dir=SiSU_Env::InfoEnv.new('')
+      if @opt.act[:sqlite][:set]==:on
+        dir.path.webserv_stub_ensure
+      end
+    end
+    def create_table
+      def conn_exec(sql)
+        if @sql_type==:pg
+          conn_exec_pg(sql)
+        elsif @sql_type==:sqlite
+          conn_exec_sqlite(sql)
+        end
+      end
+      def conn_exec_pg(sql)
+        begin
+          @conn.exec_params(sql)
+        rescue
+          if @conn.is_a?(NilClass)
+            errmsg="No pg connection (check pg dependencies)"
+            if @opt.act[:no_stop][:set]==:on
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, proceeding without pg output (as requested)")
+            else
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, STOPPING")
+              exit
+            end
+          end
+        end
+      end
+      def conn_exec_sqlite(sql)
+        begin
+          @conn.execute(sql)
+        rescue
+          if @conn.is_a?(NilClass)
+            errmsg="No sqlite3 connection (check sqlite3 dependencies)"
+            if @opt.act[:no_stop][:set]==:on
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, proceeding without sqlite output (as requested)")
+            else
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, STOPPING")
+              exit
+            end
+          end
+        end
+      end
+      def metadata_and_text
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          currently using sisu_dbi module
+          to be populated from document files
+          create tables metadata_and_text
+          data import through ruby transfer
+          }
+        end
+        create_metadata_and_text=%{
+          CREATE TABLE metadata_and_text (
+            tid                  BIGINT PRIMARY KEY,
+            /* title */
+            #{column.title.create_column}
+            #{column.title_main.create_column}
+            #{column.title_sub.create_column}
+            #{column.title_short.create_column}
+            #{column.title_edition.create_column}
+            #{column.title_note.create_column}
+            #{column.title_language.create_column}
+            #{column.title_language_char.create_column}
+            /* creator */
+            #{column.creator_author.create_column}
+            #{column.creator_author_honorific.create_column}
+            #{column.creator_author_nationality.create_column}
+            #{column.creator_editor.create_column}
+            #{column.creator_contributor.create_column}
+            #{column.creator_illustrator.create_column}
+            #{column.creator_photographer.create_column}
+            #{column.creator_translator.create_column}
+            #{column.creator_prepared_by.create_column}
+            #{column.creator_digitized_by.create_column}
+            #{column.creator_audio.create_column}
+            #{column.creator_video.create_column}
+            /* language */
+            #{column.language_document.create_column}
+            #{column.language_document_char.create_column}
+            #{column.language_original.create_column}
+            #{column.language_original_char.create_column}
+            /* date */
+            #{column.date_added_to_site.create_column}
+            #{column.date_available.create_column}
+            #{column.date_created.create_column}
+            #{column.date_issued.create_column}
+            #{column.date_modified.create_column}
+            #{column.date_published.create_column}
+            #{column.date_valid.create_column}
+            #{column.date_translated.create_column}
+            #{column.date_original_publication.create_column}
+            #{column.date_generated.create_column}
+            /* publisher */
+            #{column.publisher.create_column}
+            /* original */
+            #{column.original_publisher.create_column}
+            #{column.original_language.create_column}
+            #{column.original_language_char.create_column}
+            #{column.original_source.create_column}
+            #{column.original_institution.create_column}
+            #{column.original_nationality.create_column}
+            /* rights */
+            #{column.rights_all.create_column}
+            #{column.rights_copyright_text.create_column}
+            #{column.rights_copyright_translation.create_column}
+            #{column.rights_copyright_illustrations.create_column}
+            #{column.rights_copyright_photographs.create_column}
+            #{column.rights_copyright_preparation.create_column}
+            #{column.rights_copyright_digitization.create_column}
+            #{column.rights_copyright_audio.create_column}
+            #{column.rights_copyright_video.create_column}
+            #{column.rights_license.create_column}
+            /* classify */
+            #{column.classify_topic_register.create_column}
+            #{column.classify_subject.create_column}
+            #{column.classify_loc.create_column}
+            #{column.classify_dewey.create_column}
+            #{column.classify_keywords.create_column}
+            /* identifier */
+            #{column.identifier_oclc.create_column}
+            #{column.identifier_isbn.create_column}
+            /* notes */
+            #{column.notes_abstract.create_column}
+            #{column.notes_description.create_column}
+            #{column.notes_comment.create_column}
+            #{column.notes_history.create_column}
+            #{column.notes_coverage.create_column}
+            #{column.notes_relation.create_column}
+            /* column.notes_source.create_column */
+            #{column.notes_type.create_column}
+            #{column.notes_format.create_column}
+            #{column.notes_prefix.create_column}
+            #{column.notes_prefix_a.create_column}
+            #{column.notes_prefix_b.create_column}
+            #{column.notes_suffix.create_column}
+            /* src */
+            #{column.src_filename.create_column}
+            #{column.src_fingerprint.create_column}
+            #{column.src_filesize.create_column}
+            #{column.src_word_count.create_column}
+            #{column.src_txt.create_column}
+            /* misc */
+            #{column.fulltext.create_column}
+            #{column.links.create_column.gsub(/,$/,'')}
+/*          subj                 VARCHAR(64) NULL, */
+/*          contact              VARCHAR(100) NULL, */
+/*          information          VARCHAR(100) NULL, */
+/*          types                CHAR(1) NULL, */
+/*          writing_focus_nationality VARCHAR(100) NULL, */
+          );
+        }
+        conn_exec(create_metadata_and_text)
+        @comment.psql.metadata_and_text if @comment
+      end
+      def doc_objects                                                 # create doc_objects base
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          to be populated from documents files
+          create tables doc_objects
+          data import through ruby transfer
+          }
+        end
+        create_doc_objects=%{
+          CREATE TABLE doc_objects (
+            lid             BIGINT PRIMARY KEY,
+            metadata_tid    BIGINT REFERENCES metadata_and_text,
+            ocn             SMALLINT,
+            ocnd            VARCHAR(6),
+            ocns            VARCHAR(6),
+            clean           TEXT NULL,
+            body            TEXT NULL,
+            book_idx        TEXT NULL,
+            seg             VARCHAR(256) NULL,
+            lev_an          VARCHAR(1),
+            lev             SMALLINT NULL,
+            lev0            SMALLINT,
+            lev1            SMALLINT,
+            lev2            SMALLINT,
+            lev3            SMALLINT,
+            lev4            SMALLINT,
+            lev5            SMALLINT,
+            lev6            SMALLINT,
+            lev7            SMALLINT,
+            en_a            SMALLINT NULL,
+            en_z            SMALLINT NULL,
+            en_a_asterisk   SMALLINT NULL,
+            en_z_asterisk   SMALLINT NULL,
+            en_a_plus       SMALLINT NULL,
+            en_z_plus       SMALLINT NULL,
+            t_of            VARCHAR(16),
+            t_is            VARCHAR(16),
+            node            VARCHAR(16) NULL,
+            parent          VARCHAR(16) NULL,
+            digest_clean    CHAR(#{@@dl}),
+            digest_all      CHAR(#{@@dl}),
+            types           CHAR(1) NULL
+          );
+        }
+        conn_exec(create_doc_objects)
+        @comment.psql.doc_objects if @comment
+      end
+      def endnotes
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          to be populated from document files
+          create tables endnotes
+          data import through ruby transfer
+          }
+        end
+        create_endnotes=%{
+          CREATE TABLE endnotes (
+            nid             BIGINT PRIMARY KEY,
+            document_lid    BIGINT REFERENCES doc_objects,
+            nr              SMALLINT,
+            clean           TEXT NULL,
+            body            TEXT NULL,
+            ocn             SMALLINT,
+            ocnd            VARCHAR(6),
+            ocns            VARCHAR(6),
+            digest_clean    CHAR(#{@@dl}),
+            metadata_tid    BIGINT REFERENCES metadata_and_text
+          );
+        }
+        conn_exec(create_endnotes)
+        @comment.psql.endnotes if @comment
+      end
+      def endnotes_asterisk
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          to be populated from document files
+          create tables endnotes_asterisk
+          data import through ruby transfer
+          }
+        end
+        create_endnotes_asterisk=%{
+          CREATE TABLE endnotes_asterisk (
+            nid             BIGINT PRIMARY KEY,
+            document_lid    BIGINT REFERENCES doc_objects,
+            nr              SMALLINT,
+            clean           TEXT NULL,
+            body            TEXT NULL,
+            ocn             SMALLINT,
+            ocnd            VARCHAR(6),
+            ocns            VARCHAR(6),
+            digest_clean    CHAR(#{@@dl}),
+            metadata_tid    BIGINT REFERENCES metadata_and_text
+          );
+        }
+        conn_exec(create_endnotes_asterisk)
+        @comment.psql.endnotes_asterisk if @comment
+      end
+      def endnotes_plus
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          to be populated from document files
+          create tables endnotes_plus
+          data import through ruby transfer
+          }
+        end
+        create_endnotes_plus=%{
+          CREATE TABLE endnotes_plus (
+            nid             BIGINT PRIMARY KEY,
+            document_lid    BIGINT REFERENCES doc_objects,
+            nr              SMALLINT,
+            clean           TEXT NULL,
+            body            TEXT NULL,
+            ocn             SMALLINT,
+            ocnd            VARCHAR(6),
+            ocns            VARCHAR(6),
+            digest_clean    CHAR(#{@@dl}),
+            metadata_tid    BIGINT REFERENCES metadata_and_text
+          );
+        }
+        conn_exec(create_endnotes_plus)
+        @comment.psql.endnotes_plus if @comment
+      end
+      def urls                                                       # create doc_objects file links mapping
+        if (@opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on)
+          print %{
+          currently using sisu_dbi module
+          to be populated from doc_objects files
+          create tables urls
+          data import through ruby transfer
+          }
+        end
+        create_urls=%{
+          CREATE TABLE urls (
+            metadata_tid    BIGINT REFERENCES metadata_and_text,
+            plaintext       varchar(512),
+            html_toc        varchar(512),
+            html_doc        varchar(512),
+            xhtml           varchar(512),
+            xml_sax         varchar(512),
+            xml_dom         varchar(512),
+            odf             varchar(512),
+            pdf_p           varchar(512),
+            pdf_l           varchar(512),
+            concordance     varchar(512),
+            latex_p         varchar(512),
+            latex_l         varchar(512),
+            digest          varchar(512),
+            manifest        varchar(512),
+            markup          varchar(512),
+            sisupod         varchar(512)
+          );
+        }
+        conn_exec(create_urls)
+        @comment.psql.urls if @comment
+      end
+      self
+    end
+  end
+  class Comment < SiSU_DbColumns::Columns
+    def initialize(conn,sql_type=:pg)
+      @conn=conn
+      if sql_type == :pg then psql
+      end
+    end
+    def psql
+      def conn_execute_array(sql_arr)
+        @conn.transaction do |conn|
+          sql_arr.each do |sql|
+            conn.exec_params(sql)
+          end
+        end
+      end
+      def metadata_and_text
+        sql_arr=[
+          %{COMMENT ON Table metadata_and_text
+            IS 'contains SiSU metadata and fulltext for search (including source .sst if shared)';},
+          %{COMMENT ON COLUMN metadata_and_text.tid
+            IS 'unique';},
+          %{#{column.title.column_comment}},
+          %{#{column.title_main.column_comment}},
+          %{#{column.title_sub.column_comment}},
+          %{#{column.title_short.column_comment}},
+          %{#{column.title_edition.column_comment}},
+          %{#{column.title_note.column_comment}},
+          %{#{column.title_language.column_comment}},
+          %{#{column.title_language_char.column_comment}},
+          %{#{column.creator_author.column_comment}},
+          %{#{column.creator_author_honorific.column_comment}},
+          %{#{column.creator_author_nationality.column_comment}},
+          %{#{column.creator_editor.column_comment}},
+          %{#{column.creator_contributor.column_comment}},
+          %{#{column.creator_illustrator.column_comment}},
+          %{#{column.creator_photographer.column_comment}},
+          %{#{column.creator_translator.column_comment}},
+          %{#{column.creator_prepared_by.column_comment}},
+          %{#{column.creator_digitized_by.column_comment}},
+          %{#{column.creator_audio.column_comment}},
+          %{#{column.creator_video.column_comment}},
+          %{#{column.language_document.column_comment}},
+          %{#{column.language_document_char.column_comment}},
+          %{#{column.language_original.column_comment}},
+          %{#{column.language_original_char.column_comment}},
+          %{#{column.date_added_to_site.column_comment}},
+          %{#{column.date_available.column_comment}},
+          %{#{column.date_created.column_comment}},
+          %{#{column.date_issued.column_comment}},
+          %{#{column.date_modified.column_comment}},
+          %{#{column.date_published.column_comment}},
+          %{#{column.date_valid.column_comment}},
+          %{#{column.date_translated.column_comment}},
+          %{#{column.date_original_publication.column_comment}},
+          %{#{column.date_generated.column_comment}},
+          %{#{column.publisher.column_comment}},
+          %{#{column.original_publisher.column_comment}},
+          %{#{column.original_language.column_comment}},
+          %{#{column.original_language_char.column_comment}},
+          %{#{column.original_source.column_comment}},
+          %{#{column.original_institution.column_comment}},
+          %{#{column.original_nationality.column_comment}},
+          %{#{column.rights_all.column_comment}},
+          %{#{column.rights_copyright_text.column_comment}},
+          %{#{column.rights_copyright_translation.column_comment}},
+          %{#{column.rights_copyright_illustrations.column_comment}},
+          %{#{column.rights_copyright_photographs.column_comment}},
+          %{#{column.rights_copyright_preparation.column_comment}},
+          %{#{column.rights_copyright_digitization.column_comment}},
+          %{#{column.rights_copyright_audio.column_comment}},
+          %{#{column.rights_copyright_video.column_comment}},
+          %{#{column.rights_license.column_comment}},
+          %{#{column.classify_topic_register.column_comment}},
+          %{#{column.classify_subject.column_comment}},
+          %{#{column.classify_loc.column_comment}},
+          %{#{column.classify_dewey.column_comment}},
+          %{#{column.classify_keywords.column_comment}},
+          %{#{column.identifier_oclc.column_comment}},
+          %{#{column.identifier_isbn.column_comment}},
+          %{#{column.notes_abstract.column_comment}},
+          %{#{column.notes_comment.column_comment}},
+          %{#{column.notes_description.column_comment}},
+          %{#{column.notes_history.column_comment}},
+          %{#{column.notes_coverage.column_comment}},
+          %{#{column.notes_relation.column_comment}},
+          %{#{column.notes_type.column_comment}},
+          %{#{column.notes_format.column_comment}},
+          %{#{column.notes_prefix.column_comment}},
+          %{#{column.notes_prefix_a.column_comment}},
+          %{#{column.notes_prefix_b.column_comment}},
+          %{#{column.notes_suffix.column_comment}},
+          %{#{column.src_filename.column_comment}},
+          %{#{column.src_fingerprint.column_comment}},
+          %{#{column.src_filesize.column_comment}},
+          %{#{column.src_word_count.column_comment}},
+          %{#{column.src_txt.column_comment}},
+          %{#{column.fulltext.column_comment}},
+          %{#{column.links.column_comment}},
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def doc_objects
+        sql_arr=[
+          %{COMMENT ON Table doc_objects
+            IS 'contains searchable text of SiSU document objects';},
+          %{COMMENT ON COLUMN doc_objects.lid
+            IS 'unique';},
+          %{COMMENT ON COLUMN doc_objects.metadata_tid
+            IS 'tie to title in metadata_and_text';},
+          %{COMMENT ON COLUMN doc_objects.lev_an
+            IS 'doc level A-D 1-4';},
+          %{COMMENT ON COLUMN doc_objects.lev
+            IS 'doc level 0-7 \d\~';},
+          %{COMMENT ON COLUMN doc_objects.seg
+            IS 'segment name from level number 4 (lv 1)';},
+          %{COMMENT ON COLUMN doc_objects.ocn
+            IS 'object citation number';},
+          %{COMMENT ON COLUMN doc_objects.en_a
+            IS 'first endnote number in text object (eg. NULL or 34) (used with en_z to create range)';},
+          %{COMMENT ON COLUMN doc_objects.en_z
+            IS 'last endnote number within text object (eg. NULL, 34 or say 47) (used with en_a to create range)';},
+          %{COMMENT ON COLUMN doc_objects.en_a_asterisk
+            IS 'first endnote number in text object (eg. NULL or 34) (used with en_z_asterisk to create range)';},
+          %{COMMENT ON COLUMN doc_objects.en_z_asterisk
+            IS 'last endnote number within text object (eg. NULL, 34 or say 47) (used with en_a_asterisk to create range)';},
+          %{COMMENT ON COLUMN doc_objects.en_a_plus
+            IS 'first endnote number in text object (eg. NULL or 34) (used with en_z_plus to create range)';},
+          %{COMMENT ON COLUMN doc_objects.en_z_plus
+            IS 'last endnote number within text object (eg. NULL, 34 or say 47) (used with en_a_plus to create range)';},
+          %{COMMENT ON COLUMN doc_objects.types
+            IS 'document types seg scroll';},
+          %{COMMENT ON COLUMN doc_objects.clean
+            IS 'text object - substantive text: clean, stripped of markup';},
+          %{COMMENT ON COLUMN doc_objects.body
+            IS 'text object - substantive text: light html markup';},
+          %{COMMENT ON COLUMN doc_objects.book_idx
+            IS 'book index creation information for paragraph, if provided';},
+          %{COMMENT ON COLUMN doc_objects.lev0
+            IS 'document structure, level number 0';},
+          %{COMMENT ON COLUMN doc_objects.lev1
+            IS 'document structure, level number 1';},
+          %{COMMENT ON COLUMN doc_objects.lev2
+            IS 'document structure, level number 2';},
+          %{COMMENT ON COLUMN doc_objects.lev3
+            IS 'document structure, level number 3';},
+          %{COMMENT ON COLUMN doc_objects.lev4
+            IS 'document structure, level number 4';},
+          %{COMMENT ON COLUMN doc_objects.lev5
+            IS 'document structure, level number 5';},
+          %{COMMENT ON COLUMN doc_objects.lev6
+            IS 'document structure, level number 6';},
+          %{COMMENT ON COLUMN doc_objects.lev7
+            IS 'document structure, level number 7';},
+          %{COMMENT ON COLUMN doc_objects.t_of
+            IS 'document structure, type of object (object is of)';},
+          %{COMMENT ON COLUMN doc_objects.t_is
+            IS 'document structure, object is';},
+          %{COMMENT ON COLUMN doc_objects.node
+            IS 'document structure, object node if heading';},
+          %{COMMENT ON COLUMN doc_objects.parent
+            IS 'document structure, object parent (is a heading)';}
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def endnotes
+        sql_arr=[
+          %{COMMENT ON Table endnotes
+            IS 'contains searchable text of SiSU documents endnotes';},
+          %{COMMENT ON COLUMN endnotes.nid
+            IS 'unique';},
+          %{COMMENT ON COLUMN endnotes.document_lid
+            IS 'ties to text block from which referenced';},
+          %{COMMENT ON COLUMN endnotes.nr
+            IS 'endnote number ';},
+          %{COMMENT ON COLUMN endnotes.clean
+            IS 'endnote substantive content, stripped of markup';},
+          %{COMMENT ON COLUMN endnotes.body
+            IS 'endnote substantive content';},
+          %{COMMENT ON COLUMN endnotes.ocn
+            IS 'object citation no# <\~(\d+)> from which endnote is referenced';},
+          %{COMMENT ON COLUMN doc_objects.metadata_tid
+            IS 'tie to title in metadata_and_text - unique for each document';}
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def endnotes_asterisk
+        sql_arr=[
+          %{COMMENT ON Table endnotes_asterisk
+            IS 'contains searchable text of SiSU documents endnotes marked with asterisk';},
+          %{COMMENT ON COLUMN endnotes_asterisk.nid
+            IS 'unique';},
+          %{COMMENT ON COLUMN endnotes_asterisk.document_lid
+            IS 'ties to text block from which referenced';},
+          %{COMMENT ON COLUMN endnotes_asterisk.nr
+            IS 'endnote number ';},
+          %{COMMENT ON COLUMN endnotes_asterisk.clean
+            IS 'endnote substantive content, stripped of markup';},
+          %{COMMENT ON COLUMN endnotes_asterisk.body
+            IS 'endnote substantive content';},
+          %{COMMENT ON COLUMN endnotes_asterisk.ocn
+            IS 'object citation no# <\~(\d+)> from which endnote is referenced';},
+          %{COMMENT ON COLUMN doc_objects.metadata_tid
+            IS 'tie to title in metadata_and_text - unique for each document';}
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def endnotes_plus
+        sql_arr=[
+          %{COMMENT ON Table endnotes_plus
+            IS 'contains searchable text of SiSU documents endnotes marked with plus';},
+          %{COMMENT ON COLUMN endnotes_plus.nid
+            IS 'unique';},
+          %{COMMENT ON COLUMN endnotes_plus.document_lid
+            IS 'ties to text block from which referenced';},
+          %{COMMENT ON COLUMN endnotes_plus.nr
+            IS 'endnote number ';},
+          %{COMMENT ON COLUMN endnotes_plus.clean
+            IS 'endnote substantive content, stripped of markup';},
+          %{COMMENT ON COLUMN endnotes_plus.body
+            IS 'endnote substantive content';},
+          %{COMMENT ON COLUMN endnotes_plus.ocn
+            IS 'object citation no# <\~(\d+)> from which endnote is referenced';},
+          %{COMMENT ON COLUMN doc_objects.metadata_tid
+            IS 'tie to title in metadata_and_text - unique for each document';},
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def urls
+        sql_arr=[
+          %{COMMENT ON Table urls
+            IS 'contains base url links to different SiSU output';},
+          %{COMMENT ON COLUMN doc_objects.metadata_tid
+            IS 'tie to title in metadata_and_text - unique for each document, the mapping of rows is one to one';},
+          %{COMMENT ON COLUMN urls.plaintext
+            IS 'plaintext utf-8';},
+          %{COMMENT ON COLUMN urls.html_toc
+            IS 'table of contents for segmented html document';},
+          %{COMMENT ON COLUMN urls.html_doc
+            IS 'html document (scroll)';},
+          %{COMMENT ON COLUMN urls.xhtml
+            IS 'xhtml document (scroll)';},
+          %{COMMENT ON COLUMN urls.xml_sax
+            IS 'xml sax oriented document (scroll)';},
+          %{COMMENT ON COLUMN urls.xml_dom
+            IS 'xml dom oriented document (scroll)';},
+          %{COMMENT ON COLUMN urls.odf
+            IS 'opendocument format text';},
+          %{COMMENT ON COLUMN urls.pdf_p
+            IS 'pdf portrait';},
+          %{COMMENT ON COLUMN urls.pdf_l
+            IS 'pdf landscape';},
+          %{COMMENT ON COLUMN urls.concordance
+            IS 'rudimentary document index linked to html';},
+          %{COMMENT ON COLUMN urls.latex_p
+            IS 'latex portrait';},
+          %{COMMENT ON COLUMN urls.latex_l
+            IS 'latex_landscape';},
+          %{COMMENT ON COLUMN urls.markup
+            IS 'markup';},
+          %{COMMENT ON COLUMN urls.sisupod
+            IS 'SiSU document format .tgz (all SiSU information on document)';},
+        ]
+        conn_execute_array(sql_arr)
+      end
+      self
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** db_drop.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_drop.rb"
+# <>
+module SiSU_DbDrop
+  require_relative 'utils_response'                   # utils_response.rb
+  class Drop
+    include SiSU_Response
+    def initialize(opt,conn,db_info,sql_type)
+      @opt,@conn,@db_info,@sql_type=opt,conn,db_info,sql_type
+      case @sql_type
+      when :sqlite
+        cascade=''
+      else
+        cascade='CASCADE'
+      end
+      @drop_table=[
+        "DROP TABLE metadata_and_text #{cascade};",
+        "DROP TABLE doc_objects #{cascade};",
+        "DROP TABLE urls #{cascade};",
+        "DROP TABLE endnotes #{cascade};",
+        "DROP TABLE endnotes_asterisk #{cascade};",
+        "DROP TABLE endnotes_plus #{cascade};",
+      ]
+    end
+    def drop
+      def tables                                                              #% drop all tables
+        begin
+          msg_sqlite="as not all disk space is recovered after dropping the database << #{@db_info.sqlite.db} >>, you may be better off deleting the file, and recreating it as necessary"
+          case @sql_type
+          when :sqlite
+            puts msg_sqlite
+            ans=response?('remove sql database?')
+            if ans \
+            and File.exist?(@db_info.sqlite.db)
+              @conn.close
+              File.unlink(@db_info.sqlite.db)
+              db=SiSU_Env::InfoDb.new
+              conn=db.sqlite.conn_sqlite3
+              sdb=SiSU_DbDBI::Create.new(@opt,conn,@db_info,@sql_type)
+              sdb_index=SiSU_DbDBI::Index.new(@opt,conn,@db_info,@sql_type)
+              sdb.output_dir?
+              begin
+                sdb.create_db
+                sdb.create_table.metadata_and_text
+                sdb.create_table.doc_objects
+                sdb.create_table.endnotes
+                sdb.create_table.endnotes_asterisk
+                sdb.create_table.endnotes_plus
+                sdb.create_table.urls
+                sdb_index.create_indexes
+              rescue
+                SiSU_Errors::Rescued.new($!,$@,'-D').location do
+                  __LINE__.to_s + ':' + __FILE__
+                end
+                sdb.output_dir?
+              end
+              exit
+            else
+              @conn.transaction
+              @drop_table.each do |d|
+                begin
+                  @conn.exec_params(d)
+                rescue
+                  next
+                end
+                end
+              @conn.commit
+            end
+          when :pg
+            @conn.transaction
+            @drop_table.each do |d|
+              begin
+                @conn.exec_params(d)
+              rescue
+                next
+              end
+            end
+            @conn.commit
+          end
+        rescue
+          case @sql_type
+          when :sqlite
+            ans=response?('remove sql database?')
+            if ans and File.exist?(@db_info.sqlite.db); File.unlink(@db_info.sqlite.db)
+            end
+          else
+            @drop_table.each do |d|
+              begin
+                @conn.exec_params(d)
+              rescue
+                next
+              end
+            end
+          end
+        ensure
+        end
+      end
+      def indexes
+        def conn_execute_array(sql_arr)
+          @conn.transaction do |conn|
+            sql_arr.each do |sql|
+              begin
+                conn.exec_params(sql)
+              rescue
+                next
+              end
+            end
+          end
+        end
+        def base                                                             #% drop base indexes
+          print "\n          drop documents common indexes\n" unless @opt.act[:quiet][:set]==:on
+          sql_arr=[
+            %{DROP INDEX idx_title;},
+            %{DROP INDEX idx_author;},
+            %{DROP INDEX idx_filename;},
+            %{DROP INDEX idx_topics;},
+            %{DROP INDEX idx_ocn;},
+            %{DROP INDEX idx_digest_clean;},
+            %{DROP INDEX idx_digest_all;},
+            %{DROP INDEX idx_lev0;},
+            %{DROP INDEX idx_lev1;},
+            %{DROP INDEX idx_lev2;},
+            %{DROP INDEX idx_lev3;},
+            %{DROP INDEX idx_lev4;},
+            %{DROP INDEX idx_lev5;},
+            %{DROP INDEX idx_lev6;},
+            %{DROP INDEX idx_endnote_nr;},
+            %{DROP INDEX idx_digest_en;},
+            %{DROP INDEX idx_endnote_nr_asterisk;},
+            %{DROP INDEX idx_endnote_asterisk;},
+            %{DROP INDEX idx_digest_en_asterisk;},
+            %{DROP INDEX idx_endnote_nr_plus;},
+            %{DROP INDEX idx_endnote_plus;},
+            %{DROP INDEX idx_digest_en_plus},
+          ]
+          conn_execute_array(sql_arr)
+        end
+        def text                                                             #% drop TEXT indexes, sqlite
+          print "\n          drop documents TEXT indexes\n" unless @opt.act[:quiet][:set]==:on
+          sql_arr=[
+            %{DROP INDEX idx_clean;},
+            %{DROP INDEX idx_endnote},
+          ]
+          conn_execute_array(sql_arr)
+        end
+        self
+      end
+      indexes.base
+      @opt.act[:psql][:set]==:on ? '' : indexes.text
+      self
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** db_import.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_import.rb"
+# <>
+module SiSU_DbImport
+  require_relative 'db_columns'                         # db_columns.rb
+  require_relative 'db_load_tuple'                      # db_load_tuple.rb
+  require_relative 'db_sqltxt'                          # db_sqltxt.rb
+  require_relative 'html_lite_shared'                   # html_lite_shared.rb
+  class Import < SiSU_DbText::Prepare
+    include SiSU_Param
+    include SiSU_Screen
+    include SiSU_DbAction
+    @@dl=nil
+    @@hname=nil
+    attr_accessor :tp
+    def initialize(opt,conn,file_maint,sql_type=:pg)
+      @opt,@conn,@file_maint,@sql_type=opt,conn,file_maint,sql_type
+      @cX=SiSU_Screen::Ansi.new(@opt.act[:color_state][:set]).cX
+      @env=SiSU_Env::InfoEnv.new(@opt.fns)
+      @dal="#{@env.processing_path.ao}"
+      @fnb=if @opt.fns.empty? \
+      or @opt.selections.str.empty?
+        ''
+      else
+        @md=SiSU_Param::Parameters.new(@opt).get
+        @md.fnb
+      end
+      @fnc="#{@dal}/#{@opt.fns}.content.rbm"
+      @@seg,@@seg_full='',''                                  #create? consider placing field just before clean text as opposed to seg which contains seg(.html) name info seg_full would contain seg info for levels 5 & 6 where available eg seg_full may be 7.3 (level 5) and 7.3.1 (level 6) where seg  is 7
+      @col=Hash.new('')
+      @col[:ocn]=''
+      @counter={}
+      @db=SiSU_Env::InfoDb.new
+      if @sql_type==:sqlite
+        @driver_sqlite3=
+        (@conn.inspect.match(/^(.{10})/)[1] \
+        == @db.sqlite.conn_sqlite3.inspect.match(/^(.{10})/)[1]) \
+        ? true
+        : false
+      end
+      sql='SELECT MAX(lid) FROM doc_objects'
+      begin
+        @col[:lid] ||=0
+        @col[:lid]=@driver_sqlite3 \
+        ? @conn.execute( sql ).join.to_i
+        : @conn.exec( sql ).getvalue(0,0).to_i
+      rescue
+        if @opt.act[:maintenance][:set]==:on
+          puts "#{__FILE__}:#{__LINE__}"
+        end
+      end
+      @col[:lid]=0 if @col[:lid].nil? or @col[:lid].to_s.empty?
+      sql='SELECT MAX(nid) FROM endnotes'
+      begin
+        @id_n=@driver_sqlite3 \
+        ? @conn.execute( sql ).join.to_i
+        : @conn.exec( sql ).getvalue(0,0).to_i
+        @id_n ||=0
+      rescue
+        if @opt.act[:maintenance][:set]==:on
+          puts "#{__FILE__}:#{__LINE__}"
+        end
+      end
+      @id_n =0 if @col[:lid].nil? or @col[:lid].to_s.empty?
+      @col[:lv0]=@col[:lv1]=@col[:lv2]=@col[:lv3]=@col[:lv4]=@col[:lv5]=@col[:lv6]=@col[:lv7]=0
+      @db=SiSU_Env::InfoDb.new
+      @pdf_fn=SiSU_Env::FileOp.new(@md).base_filename
+      @@dl ||=SiSU_Env::InfoEnv.new.digest.length
+    end
+    def marshal_load
+      require_relative 'ao'                               # ao.rb
+      @ao_array=SiSU_AO::Source.new(@opt).get             # ao file drawn here
+      if (@opt.act[:verbose][:set]==:on \
+      || @opt.act[:verbose_plus][:set]==:on \
+      || @opt.act[:maintenance][:set]==:on)
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "#{@db.psql.db}::#{@opt.fns}"
+        ).puts_blue
+      end
+      SiSU_Screen::Ansi.new(
+        @opt.act[:color_state][:set],
+        'Marshal Load',
+        @fnc
+      ).puts_grey if @opt.act[:verbose][:set]==:on
+      select_first_match=%{
+        SELECT metadata_and_text.tid
+        FROM metadata_and_text
+        WHERE metadata_and_text.src_filename = '#{@md.fns}'
+        AND metadata_and_text.language_document_char = '#{@opt.lng}'
+      ;} # note, for .ssm: @md.fns (is set during runtime & is) != @opt.fns @md.opt.fns
+      file_exist=if @sql_type==:sqlite
+        begin
+          @conn.get_first_value(select_first_match)
+        rescue SQLite3::Exception => e
+          # not tested
+          puts "Exception occurred"
+          puts e
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+            "\n" \
+            + 'Attempting to initialize db' + "\n" \
+            + 'Creating db tables'
+          )
+          sdb={
+            create: SiSU_DbDBI::Create.new(@opt,@conn,@file_maint,@sql_type),
+            index: SiSU_DbDBI::Index.new(@opt,@conn,@file_maint,@sql_type),
+          }
+          db_action(sdb).create
+        end
+      else
+        begin
+          @conn.exec(select_first_match).field_values("tid")[0]
+        rescue PG::Error => e
+          err=[
+            e.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
+            e.result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
+            e.result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
+            e.result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
+            e.result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
+            e.result.error_field( PG::Result::PG_DIAG_CONTEXT ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
+          ]
+          p err
+          if err[2] =~/relation "\S+?" does not exist/ \
+          or err.inspect =~/relation "\S+?" does not exist/
+            SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+              "\n" \
+              + err[2] + "\n" \
+              + 'Attempting to initialize db' + "\n" \
+              + 'Creating db tables'
+            )
+            sdb={
+              create: SiSU_DbDBI::Create.new(@opt,@conn,@file_maint,@sql_type),
+              index: SiSU_DbDBI::Index.new(@opt,@conn,@file_maint,@sql_type),
+            }
+            db_action(sdb).create
+            retry
+          end
+        end
+      end
+      if not file_exist
+        t_d=[]                                                              # transaction_data
+        t_d << db_import_metadata
+        t_d << db_import_documents(@ao_array)
+        t_d << db_import_urls(@ao_array,@fnc)                              #import OID on/off
+        t_d=t_d.flatten
+        if (@opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          puts @conn.class if defined? @conn.class
+          puts @conn.driver_name if defined? @conn.driver_name
+          puts @conn.driver if defined? @conn.driver
+        end
+        begin                                                               #% sql
+          if @sql_type==:sqlite
+            @conn.transaction do |conn|
+              t_d.each do |sql|
+                conn.execute(sql)
+              end
+            end
+            #also 'execute' works for sqlite
+            #@conn.execute("BEGIN")
+            #  t_d.each do |sql|
+            #    @conn.execute(sql)
+            #  end
+            #@conn.execute("COMMIT")
+          else
+            #'do' works for postgresql
+            @conn.exec("BEGIN")
+              t_d.each do |sql|
+                @conn.exec(sql)
+              end
+            @conn.exec("COMMIT")
+          end
+        rescue
+          SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
+            __LINE__.to_s + ':' + __FILE__
+          end
+          sqlfn="#{@env.processing_path.sql}/#{@md.fnb}.sql"
+          sql=File.new(sqlfn,'w')
+          t_d.each {|i| sql.puts i}
+          p sqlfn
+          if @opt.act[:maintenance][:set]==:on
+            puts sql
+            p @conn.methods.sort
+            puts "#{__FILE__}:#{__LINE__}"
+          end
+        ensure
+        end
+      else
+        if file_exist
+          @db=SiSU_Env::InfoDb.new
+          puts "\nfile #{@opt.fns} in language code #{@opt.lng} already exists in database #{@db.psql.db}, use --update instead?"
+        end
+      end
+    end
+    def pf_db_import_transaction_open
+    end
+    def pf_db_import_transaction_close
+    end
+    def book_idx_hash_to_str(book_idx)
+      book_idx=book_idx ? book_idx : ''
+      book_idx_str,book_subidx_part='',''
+      if not book_idx.empty?
+        book_idx_str=''
+        book_idx.each_pair do |k0,v0|
+          book_idx_str << %{#{k0}+#{v0[:plus]}}
+          book_subidx_part=''
+          if v0[:sub].length > 0
+            v0[:sub].each do |subterms|
+               subterms.each_pair do |k1,v1|
+                 book_subidx_part << %{\n  #{k1}+#{v1[:plus]} | }
+               end
+            end
+            book_idx_str=book_idx_str + ':' + book_subidx_part
+          end
+        end
+      end
+      book_idx_str
+    end
+    def db_import_metadata                                                       #% import documents - populate database
+      if (@opt.act[:verbose][:set]==:on \
+      || @opt.act[:verbose_plus][:set]==:on \
+      || @opt.act[:maintenance][:set]==:on)
+        print %{ #{@cX.grey}import documents dbi_unit #{@cX.off} }
+      end
+      @tp={}
+      @md=SiSU_Param::Parameters.new(@opt).get
+#% sisutxt & fulltxt
+      if FileTest.exist?(@md.fns)
+        txt_arr=IO.readlines(@md.fns,'')
+        src=txt_arr.join("\n")
+        src=special_character_escape(src)
+        @tp[:sisutxt_f],@tp[:sisutxt_i]='sisutxt, ',"'#{src}', "
+        txt=clean_searchable_text_from_document_source(txt_arr)
+        #txt=special_character_escape(txt)
+        @tp[:fulltxt_f],@tp[:fulltxt_i]='fulltxt, ',"'#{txt}', "
+      end
+#% title
+      if defined? @md.title.full \
+      and @md.title.full=~/\S+/                                              # DublinCore 1 - title
+        #@tp[:title]=@md.title.full
+        #special_character_escape(@tp[:title])
+        #@tp[:title_f],@tp[:title_i]='title, ',"'#{@tp[:title]}', "
+        sql='SELECT MAX(tid) FROM metadata_and_text;'
+        begin
+          @@id_t ||=0
+          id_t=@driver_sqlite3 \
+          ? @conn.execute( sql ).join.to_i # { |x| id_t=x.join.to_i }
+          : @conn.exec( sql ).getvalue(0,0).to_i
+          @@id_t=id_t if id_t
+        rescue
+          if @opt.act[:maintenance][:set]==:on
+            puts "#{__FILE__} #{__LINE__}"
+          end
+        end
+        @@id_t+=1 #bug related, needs to be performed once at start of file, but consider moving, as, placed here it means program will fail if document header lacks @title:
+        if (@opt.act[:verbose][:set]==:on \
+        || @opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          puts %{\n#{@cX.grey}Processing file number#{@cX.off}: #{@cX.green}#{@@id_t}#{@@cX.off}}
+        end
+      end
+      ################ CLEAR ##############
+      SiSU_DbDBI::Test.new(self,@opt).verify                          #% import title names, filenames (tuple)
+      t=SiSU_DbTuple::LoadMetadata.new(@conn,@@id_t,@md,@file_maint)
+      tuple=t.tuple
+      tuple
+    end
+    def db_import_documents(ao_array)                                     #% import documents - populate main database table, import into substantive database tables (tuple)
+      begin
+        @col[:tid]=@@id_t
+        @en,@en_ast,@en_pls,@tuple_array=[],[],[],[]
+        @col[:en_a],@col[:en_z]=nil,nil
+        ao_array.each do |data|
+          data.obj=data.obj.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'\1').
+            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'\1').
+            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'\1').
+            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,'\1').
+            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,'\1').
+            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,'\1').
+            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,'\1').
+            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,'\1').
+            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,'\1').
+            gsub(/#{Mx[:gl_o]}(●)#{Mx[:gl_c]}\s*/,'\1 ').
+            gsub(/#{Mx[:tag_o]}\S+?#{Mx[:tag_c]}/,'') #check
+          @col[:seg]=@@seg
+          if data.of ==:para \
+          || data.of ==:heading \
+          || data.of ==:heading_insert \
+          || data.of ==:block \
+          || data.of ==:group      # regular text what of code-blocks grouped text etc.
+            notedata=data.obj.dup
+                                                                               #% :headings
+            if data.is==:heading \
+            && (data.ln.inspect=~/[0-3]/)
+              (
+                @col[:lev],
+                txt,@col[:ocn],
+                @col[:lev_an],
+                @col[:ocnd],@col[:ocns],
+                @col[:t_of],@col[:t_is],
+                @col[:node],@col[:parent],
+                @col[:digest_clean],@col[:digest_all]=
+                data.ln,
+                data.obj,data.ocn,
+                data.lv,
+                data.odv,data.osp,
+                data.of,data.is,
+                data.node,data.parent,
+                '',''
+              )
+              @col[:lid]+=1
+              txt=endnotes(txt).extract_any
+              body=SiSU_FormatShared::CSS_Format.new(@md,data).lev4_minus
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              if @en[0] then @en_a,@en_z=@en[0].first,@en[0].last
+              end
+              if @en_ast[0] then @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last
+              end
+              if @en_pls[0] then @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last
+              end
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              case @col[:lev]
+              when /0/ then @col[:lv0]+=1
+              when /1/ then @col[:lv1]+=1
+              when /2/ then @col[:lv2]+=1
+              when /3/ then @col[:lv3]+=1
+              when /4/ then @col[:lv4]+=1
+              end
+              @col[:lev]=@col[:plaintext]=@col[:body]=''
+            elsif data.is==:heading \
+            && data.ln==4
+              (
+                @@seg,txt,
+                @col[:ocn],@col[:lev_an],
+                @col[:ocnd],@col[:ocns],
+                @col[:t_of],@col[:t_is],
+                @col[:node],@col[:parent],
+                @col[:digest_clean],@col[:digest_all]=
+                data.name,data.obj,
+                data.ocn,data.lv,
+                data.odv,data.osp,
+                data.of,data.is,
+                data.node,data.parent,
+                '',''
+              )
+              @col[:seg]=@@seg
+              @col[:lv4]+=1
+              @col[:lid]+=1
+              @col[:lev]=4
+              @hname=if @col[:seg] \
+              and not @col[:seg].to_s.empty?
+                @@hname=@col[:seg].to_s
+              else @@hname
+              end
+              @env=SiSU_Env::InfoEnv.new(@md.fns)
+              @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
+              txt=endnotes(txt).extract_any
+              body=SiSU_FormatShared::CSS_Format.new(@md,data).lev4_plus
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              @en_a,@en_z=@en[0].first,@en[0].last if @en[0]
+              @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last if @en_ast[0]
+              @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last if @en_pls[0]
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              @col[:lev]=@col[:plaintext]=@col[:body]=''
+            elsif data.is==:heading \
+            && data.ln==5
+              (
+                txt,
+                @col[:ocn],@col[:lev_an],
+                @col[:ocnd],@col[:ocns],
+                @col[:t_of],@col[:t_is],
+                @col[:node],@col[:parent],
+                @col[:digest_clean],@col[:digest_all]=
+                data.obj,
+                data.ocn,data.lv,
+                data.odv,data.osp,
+                data.of,data.is,
+                data.node,data.parent,
+                '',''
+              )
+              @@seg_full=data.name if data.is==:heading \
+              && data.ln==5 \
+              && data.name #check data.name
+              @@seg ||='' #nil # watch
+              @col[:seg]=@@seg
+              @col[:lv5]+=1
+              @col[:lid]+=1
+              @col[:lev]=5
+              @hname=if @col[:seg] \
+              and not @col[:seg].to_s.empty?
+                @@hname=@col[:seg].to_s
+              else @@hname
+              end
+              @env=SiSU_Env::InfoEnv.new(@md.fns)
+              @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
+              txt=endnotes(txt).extract_any
+              body=SiSU_FormatShared::CSS_Format.new(@md,data).lev4_plus
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              @en_a,@en_z=@en[0].first,@en[0].last if @en[0]
+              @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last if @en_ast[0]
+              @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last if @en_pls[0]
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              @col[:lev]=@col[:plaintext]=@col[:body]=''
+            elsif data.is==:heading \
+            && data.ln==6
+              txt,       @col[:ocn],@col[:lev_an],@col[:ocnd],@col[:ocns],@col[:t_of],@col[:t_is],@col[:node],@col[:parent],@col[:digest_clean],@col[:digest_all]=
+                data.obj,data.ocn,  data.lv,      data.odv,   data.osp,   data.of,    data.is,    data.node,  data.parent,  '',                 ''
+              @@seg_full=data.name if data.is==:heading && data.ln==6 && data.name #check data.name
+              @@seg ||='' #nil # watch
+              @col[:seg]=@@seg
+              @col[:lv6]+=1
+              @col[:lid]+=1
+              @col[:lev]=6
+              @hname=if @col[:seg] \
+              and not @col[:seg].to_s.empty?
+                @@hname=@col[:seg].to_s
+              else @@hname
+              end
+              @env=SiSU_Env::InfoEnv.new(@md.fns)
+              @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
+              txt=endnotes(txt).extract_any
+              body=SiSU_FormatShared::CSS_Format.new(@md,data).lev4_plus
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              @en_a,@en_z=@en[0].first,@en[0].last if @en[0]
+              @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last if @en_ast[0]
+              @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last if @en_pls[0]
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              @col[:lev]=@col[:plaintext]=@col[:body]=''
+            elsif data.is==:heading \
+            && data.ln==7
+              txt,       @col[:ocn],@col[:lev_an],@col[:ocnd],@col[:ocns],@col[:t_of],@col[:t_is],@col[:node],@col[:parent],@col[:digest_clean],@col[:digest_all]=
+                data.obj,data.ocn,  data.lv,      data.odv,   data.osp,   data.of,    data.is,    data.node,  data.parent,  '',                 ''
+              @@seg_full=data.name if data.is==:heading && data.ln==7 && data.name #check data.name
+              @@seg ||='' #nil # watch
+              @col[:seg]=@@seg
+              @col[:lv7]+=1
+              @col[:lid]+=1
+              @col[:lev]=7
+              @hname=if @col[:seg] \
+              and not @col[:seg].to_s.empty?
+                @@hname=@col[:seg].to_s
+              else @@hname
+              end
+              @env=SiSU_Env::InfoEnv.new(@md.fns)
+              @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
+              txt=endnotes(txt).extract_any
+              body=SiSU_FormatShared::CSS_Format.new(@md,data).lev4_plus
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              @en_a,@en_z=@en[0].first,@en[0].last if @en[0]
+              @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last if @en_ast[0]
+              @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last if @en_pls[0]
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              @col[:lev]=@col[:plaintext]=@col[:body]=''
+                                                                               #% :structure :layout :comment
+            elsif data.of==:structure \
+            || data.of==:layout \
+            || data.of==:comment
+              #added watch
+                                                                               #% :
+            else                                                               #% regular text
+              @col[:lid]+=1
+              (
+                txt=''
+                txt,@col[:ocn],
+                @col[:ocnd],@col[:ocns],
+                @col[:t_of],@col[:t_is],
+                @col[:node],@col[:parent],
+                @col[:digest_clean],@col[:digest_all],
+                @col[:lev]=
+                data.obj,data.ocn,
+                data.odv,data.osp,
+                data.of,data.is,
+                '',data.parent,
+                '','',
+                9
+              )
+              @hname=if @col[:seg] \
+              and not @col[:seg].to_s.empty?
+                @@hname=@col[:seg].to_s
+              else @@hname
+              end
+              @env=SiSU_Env::InfoEnv.new(@md.fns)
+              @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
+              txt=endnotes(txt).extract_any
+              if @sql_type==:pg \
+              and txt.size > (SiSU_DbColumns::ColumnSize.new.document_clean - 1)             # examine pg build & remove limitation
+                puts "\n\nTOO LARGE (TXT - see error log)\n\n"
+                open("#{Dir.pwd}/pg_documents_error_log",'a') do |error|
+                  error.puts("\n#{@opt.fns}\nTEXT BODY\n#{@col[:body].size} object #{@col[:ocn]} -> #{@col[:body].slice(0..500)}")
+                end
+                txt=%{\n\nLARGE TEXT BLOCK OMITTED\n\n}
+              end
+              @en_a,@en_z=@en[0].first,@en[0].last if @en[0]
+              @en_a_asterisk,@en_z_asterisk=@en_ast[0].first,@en_ast[0].last if @en_ast[0]
+              @en_a_plus,@en_z_plus=@en_pls[0].first,@en_pls[0].last if @en_pls[0]
+              body=if data.is==:table
+                SiSU_FormatShared::CSS_Format.new(@md,data).html_table
+              elsif data.is==:code
+                SiSU_FormatShared::CSS_Format.new(@md,data).code
+              elsif defined? data.indent \
+              and defined? data.hang \
+              and data.indent =~/[1-9]/ \
+              and data.indent == data.hang
+                SiSU_FormatShared::CSS_Format.new(@md,data).indent(data.indent)
+              elsif defined? data.indent \
+              and defined? data.hang \
+              and data.hang =~/[0-9]/ \
+              and data.indent != data.hang
+                SiSU_FormatShared::CSS_Format.new(@md,data).hang_indent(data.hang,data.indent)
+              else
+                SiSU_FormatShared::CSS_Format.new(@md,data).norm
+              end
+              @col[:body]=clean_document_objects_body(body)
+              plaintext=@col[:body].dup
+              plaintext=strip_markup(plaintext)
+              @col[:plaintext]=clean_searchable_text_from_document_objects(plaintext)
+              book_idx=book_idx_hash_to_str(data.idx)
+              @col[:book_idx]=clean_searchable_text_from_document_objects(book_idx)
+              t=SiSU_DbTuple::LoadDocuments.new(@conn,@col,@opt,@file_maint)
+              @tuple_array << t.tuple
+              @en,@en_ast,@en_pls=[],[],[]
+              @col[:en_a]=@col[:en_z]=nil
+              @col[:lev]=@col[:plaintext]=@col[:body]=@col[:words]=''
+            end
+            if notedata =~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/                                         #% import into database endnotes tables
+              endnote_array=notedata.scan(/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/)
+              endnote_array.each do |inf|
+                if inf[/#{Mx[:en_a_o]}\d+.+?#{Mx[:en_a_c]}/]
+                  if inf[/#{Mx[:en_a_o]}(\d+)(.+?)#{Mx[:en_a_c]}/]
+                    nr,txt,digest_clean=$1,$2.strip,0
+                  end
+                  @id_n ||=0
+                  @id_n+=1
+                  txt=special_character_escape(txt)
+                  body=SiSU_FormatShared::CSS_Format.new(@md,data).endnote(nr,txt)
+                  txt=strip_markup(txt)
+                  if txt.size > (SiSU_DbColumns::ColumnSize.new.endnote_clean - 1)
+                    puts "\n\nTOO LARGE (ENDNOTE - see error log)\n\n"
+                    open("#{Dir.pwd}/pg_documents_error_log",'a') do |error|
+                      error.puts("\n#{@opt.fns}\nENDNOTE\n#{txt.size} object #{@col[:ocn]},#{@col[:ocnd]},#{@col[:ocns]} -> #{txt.slice(0..500)}")
+                    end
+                    txt=%{\n\nLARGE TEXT BLOCK OMITTED\n\n}
+                  end
+                  if txt
+                    en={
+                      type: 'endnotes',
+                      id:      @id_n,
+                      lid:     @col[:lid],
+                      nr:      nr,
+                      txt:     txt,
+                      body:    body,
+                      ocn:     @col[:ocn],
+                      ocnd:    @col[:ocnd],
+                      ocns:    @col[:ocns],
+                      id_t:    @@id_t,
+                      hash:    digest_clean
+                    }
+                    t=SiSU_DbTuple::LoadEndnotes.new(@conn,en,@opt,@file_maint)
+                    @tuple_array << t.tuple
+                  end
+                end
+              end
+              word_mode=notedata.scan(/\S+/)
+            end
+            if notedata =~/#{Mx[:en_b_o]}\*.+?#{Mx[:en_b_c]}/                                      #% import into database endnotes tables
+              endnote_array=notedata.scan(/#{Mx[:en_b_o]}\*.+?#{Mx[:en_b_c]}/)
+              endnote_array.each do |inf|
+                if inf[/#{Mx[:en_b_o]}\*\d+.+?#{Mx[:en_b_c]}/]                    # dal new endnotes 2003w31/1
+                  if inf[/#{Mx[:en_b_o]}[*](\d+)(.+?)#{Mx[:en_b_c]}/]           # dal new endnotes 2003w31/1
+                    nr,txt,digest_clean=$1,$2.strip,0
+                  end
+                  @id_n+=1
+                  txt=special_character_escape(txt)
+                  body=SiSU_FormatShared::CSS_Format.new(@md,data).endnote(nr,txt)
+                  txt=strip_markup(txt)
+                  if txt.size > (SiSU_DbColumns::ColumnSize.new.endnote_clean - 1)
+                    puts "\n\nTOO LARGE (ENDNOTE - see error log)\n\n"
+                    open("#{Dir.pwd}/pg_documents_error_log",'a') do |error|
+                      error.puts("\n#{@opt.fns}\nENDNOTE\n#{txt.size} object #{@col[:ocn]},#{@col[:ocnd]},#{@col[:ocns]} -> #{txt.slice(0..500)}")
+                    end
+                    txt=%{\n\nLARGE TEXT BLOCK OMITTED\n\n}
+                  end
+                  if txt
+                    en={
+                      type: 'endnotes_asterisk',
+                      id:      @id_n,
+                      lid:     @col[:lid],
+                      nr:      nr,
+                      txt:     txt,
+                      body:    body,
+                      ocn:     @col[:ocn],
+                      ocnd:    @col[:ocnd],
+                      ocns:    @col[:ocns],
+                      id_t:    @@id_t,
+                      hash:    digest_clean
+                    }
+                    t=SiSU_DbTuple::LoadEndnotes.new(@conn,en,@opt,@file_maint)
+                    @tuple_array << t.tuple
+                  end
+                end
+              end
+              word_mode=notedata.scan(/\S+/)
+            end
+            if notedata =~/#{Mx[:en_b_o]}\+.+?#{Mx[:en_b_c]}/                                           #% import into database endnotes tables
+              endnote_array=notedata.scan(/#{Mx[:en_b_o]}\+.+?#{Mx[:en_b_c]}/)
+              endnote_array.each do |inf|
+                if inf[/#{Mx[:en_b_o]}\+\d+.+?#{Mx[:en_b_c]}/]                        # dal new endnotes 2003w31/1
+                  if inf[/#{Mx[:en_b_o]}[+](\d+)(.+?)#{Mx[:en_b_c]}/]               # dal new endnotes 2003w31/1
+                    nr,txt,digest_clean=$1,$2.strip,0
+                  end
+                  @id_n+=1
+                  txt=special_character_escape(txt)
+                  body=SiSU_FormatShared::CSS_Format.new(@md,data).endnote(nr,txt)
+                  txt=strip_markup(txt)
+                  if txt.size > (SiSU_DbColumns::ColumnSize.new.endnote_clean - 1)
+                    puts "\n\nTOO LARGE (ENDNOTE - see error log)\n\n"
+                    open("#{Dir.pwd}/pg_documents_error_log",'a') do |error|
+                      error.puts("\n#{@opt.fns}\nENDNOTE\n#{txt.size} object #{@col[:ocn]},#{@col[:ocnd]},#{@col[:ocns]} -> #{txt.slice(0..500)}")
+                    end
+                    txt=%{\n\nLARGE TEXT BLOCK OMITTED\n\n}
+                  end
+                  if txt
+                    en={
+                      type: 'endnotes_plus',
+                      id:      @id_n,
+                      lid:     @col[:lid],
+                      nr:      nr,
+                      txt:     txt,
+                      body:    body,
+                      ocn:     @col[:ocn],
+                      ocnd:    @col[:ocnd],
+                      ocns:    @col[:ocns],
+                      id_t:    @@id_t,
+                      hash:    digest_clean
+                    }
+                    t=SiSU_DbTuple::LoadEndnotes.new(@conn,en,@opt,@file_maint)
+                    @tuple_array << t.tuple
+                  end
+                end
+              end
+              word_mode=notedata.scan(/\S+/)
+            end
+          end
+        end
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+      @tuple_array
+    end
+    def endnotes(txt)
+      @txt=txt
+      def extract_any
+        if @txt =~/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})[*+]?(\d+)\s+.+?(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/
+          endnotes(@txt).range
+          @en << endnotes(@txt).standard if @txt =~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/
+          @en_ast << endnotes(@txt).asterisk if @txt =~/#{Mx[:en_b_o]}\*.+?#{Mx[:en_b_c]}/
+          @en_pls << endnotes(@txt).plus if @txt =~/#{Mx[:en_b_o]}\+.+?#{Mx[:en_b_c]}/
+          @txt=endnotes(@txt).clean_text
+        end
+        @txt
+      end
+      def standard
+        (@txt =~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/) \
+        ? @txt.scan(/#{Mx[:en_a_o]}(\d+).+?#{Mx[:en_a_c]}/)
+        : nil
+      end
+      def asterisk
+        (@txt =~/#{Mx[:en_b_o]}\*.+?#{Mx[:en_b_c]}/) \
+        ? @txt.scan(/#{Mx[:en_b_o]}[*](\d+).+?#{Mx[:en_b_c]}/)
+        : nil
+      end
+      def plus
+        (@txt =~/#{Mx[:en_b_o]}\+.+?#{Mx[:en_b_c]}/) \
+        ? @txt.scan(/#{Mx[:en_b_o]}[+](\d+).+?#{Mx[:en_b_c]}/)
+        : nil
+      end
+      def clean_text(base_url=nil)
+        @txt=if base_url
+          @txt.gsub(/#{Mx[:en_a_o]}(\d+).+?#{Mx[:en_a_c]}/,%{\\1  }).
+            gsub(/#{Mx[:en_b_o]}([*]\d+).+?#{Mx[:en_b_c]}/,%{\\1  }).
+            gsub(/#{Mx[:en_b_o]}([+]\d+).+?#{Mx[:en_b_c]}/,%{\\1  })
+        else
+          @txt.gsub(/#{Mx[:en_a_o]}(\d+).+?#{Mx[:en_a_c]}/,'\1 ').
+            gsub(/#{Mx[:en_b_o]}([*]\d+).+?#{Mx[:en_b_c]}/,'\1 ').
+            gsub(/#{Mx[:en_b_o]}([+]\d+).+?#{Mx[:en_b_c]}/,'\1 ')
+        end
+        @txt
+      end
+      def range
+        @col[:en_a]=@col[:en_z]=nil
+        if @txt =~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}([*]\d+).+?#{Mx[:en_b_c]}|#{Mx[:en_b_o]}([+]\d+).+?#{Mx[:en_b_c]}/
+          word_array=@txt.scan(/\S+/)
+          word_array.each do |w|
+            if w[/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})[*+]?(\d+)\s+.+?(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/]                                                # not tested since change 2003w31
+              @col[:en_a]=$1 unless @col[:en_a]
+              @col[:en_z]=@col[:en_a].dup unless @col[:en_a]
+              @col[:en_z]=$1 if @col[:en_a]
+            end
+          end
+        end
+        @col
+      end
+      self
+    end
+    def db_import_urls(dbi_unit,content)                                           #% import documents OID - populate database
+      begin
+        @fnc=content
+        @env=SiSU_Env::InfoEnv.new(@opt.fns)
+        f,u={},{}
+        if @fnb.empty? \
+        or @fnb.nil?
+          p 'file output path error' #remove
+        end
+        if FileTest.file?("#{@md.file.output_path.txt.dir}/#{@md.file.base_filename.txt}")==true
+          f[:txt],u[:txt]='plaintext,', "'#{@md.file.output_path.txt.url}/#{@md.file.base_filename.txt}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.html_seg.dir}/#{@md.file.base_filename.html_segtoc}")==true
+          f[:html_toc],u[:html_toc]='html_toc,', "'#{@md.file.output_path.html_seg.url}/#{@md.file.base_filename.html_segtoc}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.html_scroll.dir}/#{@md.file.base_filename.html_scroll}")==true
+          f[:html_doc],u[:html_doc]='html_doc,', "'#{@md.file.output_path.html_scroll.url}/#{@md.file.base_filename.html_scroll}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.xhtml.dir}/#{@md.file.base_filename.xhtml}")==true
+          f[:xhtml],u[:xhtml]='xhtml,', "'#{@md.file.output_path.xhtml.url}/#{@md.file.base_filename.xhtml}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.xml_sax.dir}/#{@md.file.base_filename.xml_sax}")==true
+          f[:xml_sax],u[:xml_sax]='xml_sax,', "'#{@md.file.output_path.xml_sax.url}/#{@md.file.base_filename.xml_sax}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.xml_dom.dir}/#{@md.file.base_filename.xml_dom}")==true
+          f[:xml_dom],u[:xml_dom]='xml_dom,', "'#{@md.file.output_path.xml_dom.url}/#{@md.file.base_filename.xml_dom}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.epub.dir}/#{@md.file.base_filename.epub}")==true
+          f[:epub],u[:epub]='epub,', "'#{@md.file.output_path.epub.url}/#{@md.file.base_filename.epub}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.odt.dir}/#{@md.file.base_filename.odt}")==true
+          f[:odf],u[:odf]='odf,', "'#{@md.file.output_path.odt.url}/#{@md.file.base_filename.odt}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_p_a4}")==true #\
+        #or FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_p_letter}")==true
+          f[:pdf_p],u[:pdf_p]='pdf_p,', "'#{@md.file.output_path.pdf.url}/#{@pdf_fn.pdf_p_a4}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_l_a4}")==true #\
+        #or FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_l_letter}")==true
+          f[:pdf_l],u[:pdf_l]='pdf_l,', "'#{@md.file.output_path.pdf.url}/#{@pdf_fn.pdf_l_a4}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.html_concordance.dir}/#{@md.file.base_filename.html_concordance}")==true
+          f[:concordance],u[:concordance]='concordance,', "'#{@md.file.output_path.html_concordance.url}/#{@md.file.base_filename.html_concordance}',"
+        end
+        #if FileTest.file?("#{@md.file.output_path.x.dir}/#{@md.file.base_filename.x}")==true
+        #  f[:latex_p],u[:latex_p]='latex_p,', "'#{@md.file.output_path.x.url}/#{@md.file.base_filename.x}',"
+        #end
+        ##if FileTest.file?("#{out}/#{@fnb}/#{@opt.fns}.tex")==true
+        ##  f[:latex_p],u[:latex_p]='latex_p,', "'#{base}/#{@fnb}/#{@opt.fns}.tex',"
+        ##end
+        #if FileTest.file?("#{@md.file.output_path.x.dir}/#{@md.file.base_filename.x}")==true
+        #  f[:latex_l],u[:latex_l]='latex_l,', "'#{@md.file.output_path.x.url}/#{@md.file.base_filename.x}',"
+        #end
+        ##if FileTest.file?("#{out}/#{@fnb}/#{@opt.fns}.landscape.tex")==true
+        ##  f[:latex_l],u[:latex_l]='latex_l,', "'#{base}/#{@fnb}/#{@opt}.fns}.landscape.tex',"
+        ##end
+        if FileTest.file?("#{@md.file.output_path.digest.dir}/#{@md.file.base_filename.digest}")==true
+          f[:digest],u[:digest]='digest,', "'#{@md.file.output_path.digest.url}/#{@md.file.base_filename.digest}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.manifest.dir}/#{@md.file.base_filename.manifest}")==true #revisit, was to be text, this is html
+          f[:manifest],u[:manifest]='manifest,', "'#{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.src.dir}/#{@md.file.base_filename.src}")==true
+          f[:markup],u[:markup]='markup,', "'#{@md.file.output_path.src.url}/#{@md.file.base_filename.src}',"
+        end
+        if FileTest.file?("#{@md.file.output_path.sisupod.dir}/#{@md.file.base_filename.sisupod}")==true
+          f[:sisupod],u[:sisupod]='sisupod,', "'#{@md.file.output_path.sisupod.url}/#{@md.file.base_filename.sisupod}',"
+        end
+        t=SiSU_DbTuple::LoadUrls.new(@conn,f,u,@@id_t,@opt,@file_maint)
+        tuple=t.tuple
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+      tuple
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** db_remove.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_remove.rb"
+# <>
+module SiSU_DbRemove
+  class Remove
+    include SiSU_DbAction
+    def initialize(opt,conn,file,sql_type)
+      @opt,@conn,@file,@sql_type=opt,conn,file,sql_type
+      @md=SiSU_Param::Parameters.new(@opt).get
+      @fnb=@md.fnb
+      @db=SiSU_Env::InfoDb.new
+    end
+    def remove
+      driver_sqlite3=if @sql_type==:sqlite
+        (@conn.inspect.match(/^(.{10})/)[1]==@db.sqlite.conn_sqlite3.inspect.match(/^(.{10})/)[1]) \
+        ? true
+        : false
+      end
+      del_id=if driver_sqlite3
+        begin
+          remove_selected=%{
+            SELECT tid
+            FROM metadata_and_text
+            WHERE src_filename = '#{@md.fns}'
+            AND metadata_and_text.language_document_char = '#{@opt.lng}'
+          ;} # note, for .ssm: @md.fns (is set during runtime & is) != @opt.fns @md.opt.fns
+          @conn.get_first_value(remove_selected).to_i
+        rescue SQLite3::Exception => e
+          #not tested
+          puts "Exception occurred"
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).mark(e.inspect)
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+            "\n" \
+            + 'Attempting to initialize db' + "\n" \
+            + 'Creating db tables'
+          )
+          sdb={
+            create: SiSU_DbDBI::Create.new(@opt,@conn,@file_maint,@sql_type),
+            index: SiSU_DbDBI::Index.new(@opt,@conn,@file_maint,@sql_type),
+          }
+          db_action(sdb).create
+        end
+      else
+        begin
+          remove_selected=%{
+            SELECT metadata_and_text.tid
+            FROM metadata_and_text
+            WHERE metadata_and_text.src_filename = '#{@md.fns}'
+            AND metadata_and_text.language_document_char = '#{@opt.lng}'
+          ;} # note, for .ssm: @md.fns (is set during runtime & is) != @opt.fns @md.opt.fns
+          x=@conn.exec(remove_selected)
+          x.field_values("tid")[0]
+        rescue PG::Error => e
+          err=[
+            e.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
+            e.result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
+            e.result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
+            e.result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
+            e.result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
+            e.result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
+            e.result.error_field( PG::Result::PG_DIAG_CONTEXT ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
+            e.result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
+          ]
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).mark("\n" + err.inspect)
+          if err[2] =~/relation "\S+?" does not exist/ \
+          or err.inspect =~/relation "\S+?" does not exist/
+            SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+              "\n" \
+              + err[2] + "\n" \
+              + 'Attempting to initialize db' + "\n" \
+              + 'Creating db tables'
+            )
+            sdb={
+              create: SiSU_DbDBI::Create.new(@opt,@conn,@file_maint,@sql_type),
+              index: SiSU_DbDBI::Index.new(@opt,@conn,@file_maint,@sql_type),
+            }
+            db_action(sdb).create
+          end
+        end
+      end
+      if del_id
+        sql_entry=[
+          "DELETE FROM endnotes WHERE metadata_tid = '#{del_id}';",
+          "DELETE FROM endnotes_asterisk WHERE metadata_tid = '#{del_id}';",
+          "DELETE FROM endnotes_plus WHERE metadata_tid = '#{del_id}';",
+          "DELETE FROM doc_objects WHERE metadata_tid = '#{del_id}';",
+          "DELETE FROM urls WHERE metadata_tid = '#{del_id}';",
+          "DELETE FROM metadata_and_text WHERE metadata_and_text.tid = '#{del_id}';",
+        ]
+        if driver_sqlite3
+          @conn.transaction
+          sql_entry.each do |s|
+            begin
+              @conn.execute(s)
+            rescue
+              next
+            end
+          end
+          @conn.commit if driver_sqlite3
+        else
+          sql_entry.each do |s|
+            begin
+              @conn.exec_params(s)
+            rescue
+              next
+            end
+          end
+        end
+        if @opt.act[:maintenance][:set]==:on
+          @file.puts sql_entry
+        end
+      else
+        if (@opt.act[:verbose][:set]==:on \
+        || @opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          SiSU_Screen::Ansi.new(
+            @opt.selections.str,
+            "no such file in database #{@db.psql.db}::#{@opt.fns}"
+          ).puts_grey
+        end
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* db_load_tuple.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_load_tuple.rb"
+# <>
+module SiSU_DbTuple
+  require_relative 'db_columns'                         # db_columns.rb
+  class LoadDocuments
+    require_relative 'dp'                               # dp.rb
+      include SiSU_Param
+    def initialize(conn,col,opt,file_maint)
+      @conn,@col,@opt,@file_maint=conn,col,opt,file_maint
+      @col[:lev]=@col[:lev].to_i
+      unless @col[:lev].inspect=~/^[0-7]/ \
+      or @col[:lev]==0..7
+        @col[:lev]=9
+      end
+      @col[:ocn]=0 unless @col[:ocn].inspect=~/\d+/
+      @cX=SiSU_Screen::Ansi.new(@opt.act[:color_state][:set]).cX
+    end
+    def tuple                                                                    #% import line
+      sql_entry=if @col[:en_a]
+        "INSERT INTO doc_objects (lid, metadata_tid, lev, lev_an, clean, body, book_idx, ocn, ocnd, ocns, seg, lev0, lev1, lev2, lev3, lev4, lev5, lev6, lev7, en_a, en_z, t_of, t_is, node, parent, digest_clean, digest_all) " +
+        "VALUES (#{@col[:lid]}, #{@col[:tid]}, #{@col[:lev]}, '#{@col[:lev_an]}', '#{@col[:plaintext]}', '#{@col[:body]}', '#{@col[:book_idx]}', '#{@col[:ocn]}', '#{@col[:ocnd]}', '#{@col[:ocns]}', '#{@col[:seg]}', '#{@col[:lv0]}', '#{@col[:lv1]}', '#{@col[:lv2]}', '#{@col[:lv3]}', '#{@col[:lv4]}', '#{@col[:lv5]}', '#{@col[:lv6]}', '#{@col[:lv7]}', '#{@col[:en_a]}', '#{@col[:en_z]}', '#{@col[:t_of]}', '#{@col[:t_is]}', '#{@col[:node]}', '#{@col[:parent]}', '#{@col[:digest_clean]}', '#{@col[:digest_all]}');"
+      else
+        "INSERT INTO doc_objects (lid, metadata_tid, lev, lev_an, clean, body, book_idx, ocn, ocnd, ocns, seg, lev0, lev1, lev2, lev3, lev4, lev5, lev6, lev7, t_of, t_is, node, parent, digest_clean, digest_all) " +
+        "VALUES (#{@col[:lid]}, #{@col[:tid]}, #{@col[:lev]}, '#{@col[:lev_an]}', '#{@col[:plaintext]}', '#{@col[:body]}', '#{@col[:book_idx]}', '#{@col[:ocn]}', '#{@col[:ocnd]}', '#{@col[:ocns]}', '#{@col[:seg]}', '#{@col[:lv0]}', '#{@col[:lv1]}', '#{@col[:lv2]}', '#{@col[:lv3]}', '#{@col[:lv4]}', '#{@col[:lv5]}', '#{@col[:lv6]}', '#{@col[:lv7]}', '#{@col[:t_of]}', '#{@col[:t_is]}', '#{@col[:node]}', '#{@col[:parent]}', '#{@col[:digest_clean]}', '#{@col[:digest_all]}');"
+      end
+      if @opt.act[:maintenance][:set]==:on
+          puts @file_maint.inspect
+          puts sql_entry
+          @file_maint.puts sql_entry
+      elsif @opt.act[:verbose_plus][:set]==:on
+          puts sql_entry
+      end
+      if @opt.act[:verbose][:set]==:on
+        if @col[:lev].inspect =~/[0-35-7]/
+          lev=case @col[:lev].inspect
+          when /0/ then ':A'
+          when /1/ then ':B'
+          when /2/ then ':C'
+          when /3/ then ':D'
+          when /5/ then ' 2'
+          when /6/ then ' 3'
+          when /7/ then ' 4'
+          end
+          puts %{#{lev}>\t#{@col[:lv0]}\t#{@col[:lv1]}\t#{@col[:lv2]}\t#{@col[:lv3]}\t#{@col[:lv4]}\t#{@col[:lv5]}\t#{@col[:lv6]}\t#{@col[:lv7]}\t#{@col[:ocn]}\t#{@col[:node]}\t#{@col[:ocns]}}
+        elsif @col[:lev].inspect =~/[4]/
+          puts %{ #{@cX.green}1>#{@cX.off}\t#{@col[:lv0]}\t#{@col[:lv1]}\t#{@col[:lv2]}\t#{@col[:lv3]}\t#{@col[:lv4]}\t#{@col[:lv5]}\t#{@col[:lv6]}\t#{@col[:lv7]}\t#{@col[:ocn]}\t#{@col[:node]}\t#{@col[:ocns]}\t#{@col[:seg]}}
+        end
+      end
+      sql_entry
+    end
+  end
+  class LoadMetadata #< SiSU_DbColumns::Columns
+    def initialize(conn,id,md,file_maint)
+      @conn,@id,@md,@file_maint=conn,id,md,file_maint
+      @tp=SiSU_DbColumns::Columns.new(md)
+    end
+    def tuple
+      sql_entry="INSERT INTO metadata_and_text (
+#{@tp.column.title.tuple[0]}
+#{@tp.column.title_main.tuple[0]}
+#{@tp.column.title_sub.tuple[0]}
+#{@tp.column.title_short.tuple[0]}
+#{@tp.column.title_edition.tuple[0]}
+#{@tp.column.title_note.tuple[0]}
+#{@tp.column.title_language.tuple[0]}
+#{@tp.column.title_language_char.tuple[0]}
+#{@tp.column.creator_author.tuple[0]}
+#{@tp.column.creator_author_honorific.tuple[0]}
+#{@tp.column.creator_author_nationality.tuple[0]}
+#{@tp.column.creator_editor.tuple[0]}
+#{@tp.column.creator_contributor.tuple[0]}
+#{@tp.column.creator_illustrator.tuple[0]}
+#{@tp.column.creator_photographer.tuple[0]}
+#{@tp.column.creator_translator.tuple[0]}
+#{@tp.column.creator_prepared_by.tuple[0]}
+#{@tp.column.creator_digitized_by.tuple[0]}
+#{@tp.column.creator_audio.tuple[0]}
+#{@tp.column.creator_video.tuple[0]}
+#{@tp.column.language_document.tuple[0]}
+#{@tp.column.language_document_char.tuple[0]}
+#{@tp.column.language_original.tuple[0]}
+#{@tp.column.language_original_char.tuple[0]}
+#{@tp.column.date_added_to_site.tuple[0]}
+#{@tp.column.date_available.tuple[0]}
+#{@tp.column.date_created.tuple[0]}
+#{@tp.column.date_issued.tuple[0]}
+#{@tp.column.date_modified.tuple[0]}
+#{@tp.column.date_published.tuple[0]}
+#{@tp.column.date_valid.tuple[0]}
+#{@tp.column.date_translated.tuple[0]}
+#{@tp.column.date_original_publication.tuple[0]}
+#{@tp.column.date_generated.tuple[0]}
+#{@tp.column.publisher.tuple[0]}
+#{@tp.column.original_publisher.tuple[0]}
+#{@tp.column.original_language.tuple[0]}
+#{@tp.column.original_language_char.tuple[0]}
+#{@tp.column.original_source.tuple[0]}
+#{@tp.column.original_institution.tuple[0]}
+#{@tp.column.original_nationality.tuple[0]}
+#{@tp.column.rights_all.tuple[0]}
+#{@tp.column.rights_copyright_text.tuple[0]}
+#{@tp.column.rights_copyright_translation.tuple[0]}
+#{@tp.column.rights_copyright_illustrations.tuple[0]}
+#{@tp.column.rights_copyright_photographs.tuple[0]}
+#{@tp.column.rights_copyright_preparation.tuple[0]}
+#{@tp.column.rights_copyright_digitization.tuple[0]}
+#{@tp.column.rights_copyright_audio.tuple[0]}
+#{@tp.column.rights_copyright_video.tuple[0]}
+#{@tp.column.rights_license.tuple[0]}
+#{@tp.column.classify_topic_register.tuple[0]}
+#{@tp.column.classify_subject.tuple[0]}
+#{@tp.column.classify_loc.tuple[0]}
+#{@tp.column.classify_dewey.tuple[0]}
+#{@tp.column.classify_keywords.tuple[0]}
+#{@tp.column.identifier_oclc.tuple[0]}
+#{@tp.column.identifier_isbn.tuple[0]}
+#{@tp.column.notes_abstract.tuple[0]}
+#{@tp.column.notes_description.tuple[0]}
+#{@tp.column.notes_comment.tuple[0]}
+#{@tp.column.notes_history.tuple[0]}
+#{@tp.column.notes_format.tuple[0]}
+#{@tp.column.notes_relation.tuple[0]}
+#{@tp.column.notes_coverage.tuple[0]}
+#{@tp.column.notes_type.tuple[0]}
+#{@tp.column.notes_prefix.tuple[0]}
+#{@tp.column.notes_prefix_a.tuple[0]}
+#{@tp.column.notes_prefix_b.tuple[0]}
+#{@tp.column.notes_suffix.tuple[0]}
+#{@tp.column.src_filename.tuple[0]}
+#{@tp.column.src_fingerprint.tuple[0]}
+#{@tp.column.src_filesize.tuple[0]}
+#{@tp.column.src_word_count.tuple[0]}
+#{@tp.column.src_txt.tuple[0]}
+#{@tp.column.fulltext.tuple[0]}
+tid)
+" +
+       "VALUES (
+#{@tp.column.title.tuple[1]}
+#{@tp.column.title_main.tuple[1]}
+#{@tp.column.title_sub.tuple[1]}
+#{@tp.column.title_short.tuple[1]}
+#{@tp.column.title_edition.tuple[1]}
+#{@tp.column.title_note.tuple[1]}
+#{@tp.column.title_language.tuple[1]}
+#{@tp.column.title_language_char.tuple[1]}
+#{@tp.column.creator_author.tuple[1]}
+#{@tp.column.creator_author_honorific.tuple[1]}
+#{@tp.column.creator_author_nationality.tuple[1]}
+#{@tp.column.creator_editor.tuple[1]}
+#{@tp.column.creator_contributor.tuple[1]}
+#{@tp.column.creator_illustrator.tuple[1]}
+#{@tp.column.creator_photographer.tuple[1]}
+#{@tp.column.creator_translator.tuple[1]}
+#{@tp.column.creator_prepared_by.tuple[1]}
+#{@tp.column.creator_digitized_by.tuple[1]}
+#{@tp.column.creator_audio.tuple[1]}
+#{@tp.column.creator_video.tuple[1]}
+#{@tp.column.language_document.tuple[1]}
+#{@tp.column.language_document_char.tuple[1]}
+#{@tp.column.language_original.tuple[1]}
+#{@tp.column.language_original_char.tuple[1]}
+#{@tp.column.date_added_to_site.tuple[1]}
+#{@tp.column.date_available.tuple[1]}
+#{@tp.column.date_created.tuple[1]}
+#{@tp.column.date_issued.tuple[1]}
+#{@tp.column.date_modified.tuple[1]}
+#{@tp.column.date_published.tuple[1]}
+#{@tp.column.date_valid.tuple[1]}
+#{@tp.column.date_translated.tuple[1]}
+#{@tp.column.date_original_publication.tuple[1]}
+#{@tp.column.date_generated.tuple[1]}
+#{@tp.column.publisher.tuple[1]}
+#{@tp.column.original_publisher.tuple[1]}
+#{@tp.column.original_language.tuple[1]}
+#{@tp.column.original_language_char.tuple[1]}
+#{@tp.column.original_source.tuple[1]}
+#{@tp.column.original_institution.tuple[1]}
+#{@tp.column.original_nationality.tuple[1]}
+#{@tp.column.rights_all.tuple[1]}
+#{@tp.column.rights_copyright_text.tuple[1]}
+#{@tp.column.rights_copyright_translation.tuple[1]}
+#{@tp.column.rights_copyright_illustrations.tuple[1]}
+#{@tp.column.rights_copyright_photographs.tuple[1]}
+#{@tp.column.rights_copyright_preparation.tuple[1]}
+#{@tp.column.rights_copyright_digitization.tuple[1]}
+#{@tp.column.rights_copyright_audio.tuple[1]}
+#{@tp.column.rights_copyright_video.tuple[1]}
+#{@tp.column.rights_license.tuple[1]}
+#{@tp.column.classify_topic_register.tuple[1]}
+#{@tp.column.classify_subject.tuple[1]}
+#{@tp.column.classify_loc.tuple[1]}
+#{@tp.column.classify_dewey.tuple[1]}
+#{@tp.column.classify_keywords.tuple[1]}
+#{@tp.column.identifier_oclc.tuple[1]}
+#{@tp.column.identifier_isbn.tuple[1]}
+#{@tp.column.notes_abstract.tuple[1]}
+#{@tp.column.notes_comment.tuple[1]}
+#{@tp.column.notes_description.tuple[1]}
+#{@tp.column.notes_history.tuple[1]}
+#{@tp.column.notes_format.tuple[1]}
+#{@tp.column.notes_relation.tuple[1]}
+#{@tp.column.notes_coverage.tuple[1]}
+#{@tp.column.notes_type.tuple[1]}
+#{@tp.column.notes_prefix.tuple[1]}
+#{@tp.column.notes_prefix_a.tuple[1]}
+#{@tp.column.notes_prefix_b.tuple[1]}
+#{@tp.column.notes_suffix.tuple[1]}
+#{@tp.column.src_filename.tuple[1]}
+#{@tp.column.src_fingerprint.tuple[1]}
+#{@tp.column.src_filesize.tuple[1]}
+#{@tp.column.src_word_count.tuple[1]}
+#{@tp.column.src_txt.tuple[1]}
+#{@tp.column.fulltext.tuple[1]}
+#{@id}
+);"
+      if @md.opt.act[:maintenance][:set]==:on
+        puts "maintenance mode on: creating sql transaction file (for last transaction set (document) only):\n\t#{@file_maint.inspect}"
+        @file_maint.puts sql_entry
+      end
+      sql_entry
+    end
+  end
+  class LoadUrls
+    def initialize(conn,f,u,id,opt,file_maint)
+      @conn,@f,@u,@id,@opt,@file_maint=conn,f,u,id,opt,file_maint
+    end
+    def tuple
+      sql_entry="INSERT INTO urls (#{@f[:txt]} #{@f[:html_toc]} #{@f[:html_doc]} #{@f[:xhtml]} #{@f[:xml_sax]} #{@f[:xml_dom]} #{@f[:odf]} #{@f[:pdf_p]} #{@f[:pdf_l]} #{@f[:concordance]} #{@f[:latex_p]} #{@f[:latex_l]} #{@f[:manifest]} #{@f[:digest]} #{@f[:markup]} #{@f[:sisupod]} metadata_tid) " +
+      "VALUES (#{@u[:txt]} #{@u[:html_toc]} #{@u[:html_doc]} #{@u[:xhtml]} #{@u[:xml_sax]} #{@u[:xml_dom]} #{@u[:odf]} #{@u[:pdf_p]} #{@u[:pdf_l]} #{@u[:concordance]} #{@u[:latex_p]} #{@u[:latex_l]} #{@u[:manifest]} #{@u[:digest]} #{@u[:markup]} #{@u[:sisupod]} #{@id});"
+      if @opt.act[:maintenance][:set]==:on
+        @file_maint.puts sql_entry
+      end
+      sql_entry
+    end
+  end
+  class LoadEndnotes
+    def initialize(conn,en,opt,file_maint)
+      @conn,@en,@opt,@file_maint=conn,en,opt,file_maint
+    end
+    def tuple
+      sql_entry="INSERT INTO #{@en[:type]} (nid, document_lid, nr, clean, body, ocn, ocnd, ocns, metadata_tid, digest_clean) " +
+      "VALUES ('#{@en[:id]}', '#{@en[:lid]}', '#{@en[:nr]}', '#{@en[:txt]}', '#{@en[:body]}', '#{@en[:ocn]}', '#{@en[:ocnd]}', '#{@en[:ocns]}', '#{@en[:id_t]}', '#{@en[:hash]}');"
+      if @opt.act[:maintenance][:set]==:on
+        @file_maint.puts sql_entry
+      end
+      sql_entry
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* db_select.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_select.rb"
+# <>
+module SiSU_DbAction
+  def db_action(sdb)
+    @sdb=sdb
+    def createdb
+      @sdb[:create].output_dir?
+      begin
+        @sdb[:create].create_db
+      rescue
+        @sdb[:create].output_dir?
+      end
+    end
+    def drop
+      @sdb[:drop].drop.tables
+    end
+    def create
+      @sdb[:create].output_dir?
+      begin
+        @sdb[:create].create_table.metadata_and_text
+        @sdb[:create].create_table.doc_objects
+        @sdb[:create].create_table.endnotes
+        @sdb[:create].create_table.endnotes_asterisk
+        @sdb[:create].create_table.endnotes_plus
+        @sdb[:create].create_table.urls
+        @sdb[:index].create_indexes
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,'--sqlite').location
+        @sdb[:create].output_dir? do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def import
+      db_exist?
+      @sdb[:import].marshal_load
+      tell=case @sql_type
+      when :sqlite
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "sqlite3 #{@db.sqlite.db} database?"
+        )
+      when :pg
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "pgaccess or psql #{@db.psql.db} database?"
+        )
+      else '???'
+      end
+      tell.puts_grey if @opt.act[:verbose][:set]==:on
+    end
+    def remove
+      db_exist?
+      @sdb[:remove_doc].remove
+    end
+    def update
+      remove
+      import
+    end
+    self
+  end
+end
+module SiSU_DbSelect
+  class Case
+    include SiSU_DbAction
+    def initialize(opt,conn='',sql_type=:pg)
+      @opt,@conn,@sql_type=opt,conn,sql_type
+      @db=SiSU_Env::InfoDb.new
+      @file_maint=sql_maintenance_file
+      @sdb={
+        create: SiSU_DbDBI::Create.new(@opt,@conn,@file_maint,@sql_type),
+        index: SiSU_DbDBI::Index.new(@opt,@conn,@file_maint,@sql_type),
+        drop: SiSU_DbDBI::Drop.new(@opt,@conn,@db,@sql_type),
+      }
+      if (@opt.act[:psql_import][:set]==:on \
+      || @opt.act[:psql_update][:set]==:on) \
+      or (@opt.act[:sqlite_import][:set]==:on \
+      || @opt.act[:sqlite_update][:set]==:on)
+        @sdb[:import]=SiSU_DbDBI::Import.new(@opt,@conn,@file_maint,@sql_type)
+        @sdb[:remove_doc]=SiSU_DbDBI::Remove.new(@opt,@conn,@file_maint,@sql_type)
+      elsif (@opt.act[:psql_remove][:set]==:on \
+      or @opt.act[:sqlite_remove][:set]==:on)
+        @sdb[:remove_doc]=SiSU_DbDBI::Remove.new(@opt,@conn,@file_maint,@sql_type)
+      end
+    end
+    def db_exist?
+      if @sql_type==:sqlite \
+      and (not (FileTest.file?(@db.sqlite.db)) \
+      or FileTest.zero?(@db.sqlite.db))
+        puts %{no connection with sqlite database established, you may need to run:\n} \
+        + %{    sisu --sqlite --createall\n} \
+        + %{  before attempting to populate the database}
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+          "\n" \
+          + 'Attempting to initialize db' + "\n" \
+          + 'Creating db tables'
+        )
+        db_action(@sdb).create
+      end
+      if @conn.is_a?(NilClass)
+        if @sql_type==:sqlite
+          puts %{no connection with sqlite database established, you may need to run:\n} \
+          + %{    sisu --sqlite --createall\n} \
+          + %{  before attempting to populate the database}
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:yellow).mark(
+            "\n" \
+            + 'Attempting to initialize db' + "\n" \
+            + 'Creating db tables'
+          )
+          db_action(@sdb).create
+          @db.sqlite.db
+        else
+          puts %{no connection with pg database established, you may need to run:\n} \
+          + %{    createdb "#{@db.psql.db}"\n} \
+          + %{  after that don't forget to run:\n} \
+          + %{    sisu --pg --createall\n} \
+          + %{  before attempting to populate the database}
+          @db.psql.db
+        end
+        exit
+      end
+    end
+    def sql_maintenance_file
+      file=if @opt.act[:maintenance][:set]==:on
+        if @opt.fns and not @opt.fns.empty?
+          @env=SiSU_Env::InfoEnv.new(@opt.fns) if @opt.fns
+          if @sql_type ==:sqlite
+            puts "\n#{@env.processing_path.sqlite}/#{@opt.fns}.sql"
+          end
+          @db=SiSU_Env::InfoDb.new
+          @job="sqlite3 #{@db.sqlite.db} < #{@env.processing_path.sqlite}/#{@opt.fns}.sql"
+          if @sql_type ==:sqlite
+            File.new("#{@env.processing_path.sqlite}/#{@opt.fns}.sql",'w+')
+          else
+            File.new("#{@env.processing_path.postgresql}/#{@opt.fns}.sql",'w+')
+          end
+        elsif @opt.fns \
+        and (@opt.act[:sqlite_create][:set] ==:on \
+        || @opt.act[:psql_create][:set] ==:on)
+          nil #sort variations later
+        else nil
+        end
+      else nil
+      end
+      file
+    end
+    def cases
+      if @opt.act[:psql_drop][:set] ==:on \
+      or @opt.act[:sqlite_drop][:set] ==:on
+        db_action(@sdb).drop
+      end
+      if @opt.act[:psql_createdb][:set] ==:on \
+      or @opt.act[:sqlite_createdb][:set] ==:on
+        db_action(@sdb).createdb
+      end
+      if @opt.act[:psql_create][:set] ==:on \
+      or @opt.act[:sqlite_create][:set] ==:on
+        db_action(@sdb).create
+      end
+      if @opt.act[:psql_update][:set] ==:on \
+      or @opt.act[:sqlite_update][:set] ==:on
+        db_action(@sdb).update
+      else
+        if @opt.act[:psql_remove][:set] ==:on \
+        or @opt.act[:sqlite_remove][:set] ==:on
+          db_action(@sdb).remove
+        end
+        if @opt.act[:psql_import][:set] ==:on \
+        or @opt.act[:sqlite_import][:set] ==:on
+          db_action(@sdb).import
+        end
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* structure
+** db_columns.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_columns.rb"
+# <>
+module SiSU_DbColumns
+  require_relative 'se'                                # se.rb
+  require_relative 'db_sqltxt'                         # db_sqltxt.rb
+  class Columns < SiSU_DbText::Prepare
+    def initialize(md=nil)
+      @md=md
+      @db=SiSU_Env::InfoDb.new #watch
+      @lang ||=SiSU_i18n::Languages.new
+      if defined? md.opt.act \
+      and ((md.opt.act[:psql_import][:set]==:on \
+      || md.opt.act[:psql_update][:set]==:on) \
+      or (md.opt.act[:sqlite_import][:set]==:on \
+      || md.opt.act[:sqlite_update][:set]==:on)) \
+      and FileTest.exist?(md.fns)
+        txt_arr=IO.readlines(md.fns,'')
+        src=txt_arr.join("\n")
+        if @db.share_source?
+          @sisutxt=special_character_escape(src)
+        else @sisutxt=''
+        end
+        @fulltext=clean_searchable_text_from_document_objects(txt_arr)
+       else @sisutxt,@fulltext='',''
+      end
+    end
+#% structures
+    #def column_define
+    #  def varchar(name,size)
+    #    "#{name}                VARCHAR(#{size}) NULL,"
+    #  end
+    #end
+=begin
+#% title
+@title:
+ :subtitle:
+ :short:
+ :edition:
+ :language:
+ :note:
+=end
+    def column
+      def title                          # DublinCore 1 - title
+        def name
+          'title'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_title]}) NOT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata full document title [DC1]';}
+        end
+        def tuple
+          if defined? @md.title.full \
+          and @md.title.full=~/\S+/
+            txt=@md.title.full
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_main
+        def name
+          'title_main'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_title_part]}) NOT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata main document title';}
+        end
+        def tuple
+          if defined? @md.title.main \
+          and @md.title.main=~/\S+/
+            txt=@md.title.main
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_sub
+        def name
+          'title_sub'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_title_part]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document subtitle';}
+        end
+        def tuple
+          if defined? @md.title.sub \
+          and @md.title.sub=~/\S+/
+            txt=@md.title.sub
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_short
+        def name
+          'title_short'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_title_part]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document short title if any';}
+        end
+        def tuple
+          if defined? @md.title.short \
+          and @md.title.short=~/\S+/
+            txt=@md.title.short
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_edition
+        def name
+          'title_edition'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_title_edition]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document edition (version)';}
+        end
+        def tuple
+          if defined? @md.title.edition \
+          and @md.title.edition=~/\S+/
+            txt=@md.title.edition
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_note
+        def name
+          'title_note'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document notes associated with title';}
+        end
+        def tuple
+          if defined? @md.title.note \
+          and @md.title.note=~/\S+/
+            txt=@md.title.note
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_language
+        def name
+          'title_language'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document language [DC12]';}
+        end
+        def tuple
+          if @lang.list[@md.opt.lng][:n]
+            txt=@lang.list[@md.opt.lng][:n]
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def title_language_char            # consider
+        def name
+          'title_language_char'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language_char]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'metadata document language iso code';}
+        end
+        def tuple
+          if defined? @md.opt.lng \
+          and @md.opt.lng=~/\S+/
+            txt=@md.opt.lng
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% creator
+@creator:
+ :author:
+ :editor:
+ :contributor:
+ :illustrator:
+ :photographer:
+ :translator:
+ :prepared_by:
+ :digitized_by:
+ :audio:
+ :video:
+=end
+      def creator_author                 # DublinCore 2 - creator/author (author)
+        def name
+          'creator_author'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document author (creator) [DC2]';}
+        end
+        def tuple
+          if defined? @md.creator.author_detail \
+          and @md.creator.author_detail.is_a?(Array) \
+          and @md.creator.author_detail.length > 0
+            txt=''
+            @md.creator.author_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_author_honorific       # consider
+        def name
+          'creator_author_hon'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_creator_misc_short]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document author honorific (title e.g, Ms. Dr. Prof.)';}
+        end
+        def tuple
+          if defined? @md.creator.author_hon \
+          and @md.creator.author_hon=~/\S+/
+            txt=@md.creator.author_hon
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_author_nationality     # consider
+        def name
+          'creator_author_nationality'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_creator_misc_short]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata nationality of document author (creator)';}
+        end
+        def tuple
+          if defined? @md.creator.author_nationality_detail \
+          and @md.creator.author_nationality=~/\S+/
+            txt=@md.creator.author_nationality_detail
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_editor
+        def name
+          'creator_editor'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document editor name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.editor_detail \
+          and @md.creator.editor_detail.is_a?(Array) \
+          and @md.creator.editor_detail.length > 0
+            txt=''
+            @md.creator.editor_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_contributor            # DublinCore 6 - contributor
+        def name
+          'creator_contributor'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document contributor name(s) [DC6]';}
+        end
+        def tuple
+          if defined? @md.creator.contributor_detail \
+          and @md.creator.contributor_detail.is_a?(Array) \
+          and @md.creator.contributor_detail.length > 0
+            txt=''
+            @md.creator.contributor_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_illustrator
+        def name
+          'creator_illustrator'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document illustrator name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.illustrator_detail \
+          and @md.creator.illustrator_detail.is_a?(Array) \
+          and @md.creator.illustrator_detail.length > 0
+            txt=''
+            @md.creator.illustrator_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_photographer
+        def name
+          'creator_photographer'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document photographer name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.photographer_detail \
+          and @md.creator.photographer_detail.is_a?(Array) \
+          and @md.creator.photographer_detail.length > 0
+            txt=''
+            @md.creator.photographer_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_translator
+        def name
+          'creator_translator'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document translator name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.translator_detail \
+          and @md.creator.translator_detail.is_a?(Array) \
+          and @md.creator.translator_detail.length > 0
+            txt=''
+            @md.creator.translator_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_prepared_by
+        def name
+          'creator_prepared_by'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document prepared by name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.prepared_by_detail \
+          and @md.creator.prepared_by_detail.is_a?(Array) \
+          and @md.creator.prepared_by_detail.length > 0
+            txt=''
+            @md.creator.prepared_by_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_digitized_by
+        def name
+          'creator_digitized_by'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document digitized by name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.digitized_by_detail \
+          and @md.creator.digitized_by_detail.is_a?(Array) \
+          and @md.creator.digitized_by_detail.length > 0
+            txt=''
+            @md.creator.digitized_by_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_audio
+        def name
+          'creator_audio'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document audio by name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.audio_detail \
+          and @md.creator.audio_detail.is_a?(Array) \
+          and @md.creator.audio_detail.length > 0
+            txt=''
+            @md.creator.audio_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def creator_video
+        def name
+          'creator_video'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document video by name(s)';}
+        end
+        def tuple
+          if defined? @md.creator.video_detail \
+          and @md.creator.video_detail.is_a?(Array) \
+          and @md.creator.video_detail.length > 0
+            txt=''
+            @md.creator.video_detail.each do |h|
+              txt=txt + %{#{h[:the]}, #{h[:others]}; }
+            end
+            txt=txt.gsub(/[;, ]+\s*$/,'')
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% language
+#taken from other fields
+@title:
+ :language:
+@original:
+ :language:
+#not available -->
+#@language:
+# :document:
+# :original:
+=end
+      def language_document
+        def name
+          'language_document'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document language';}
+        end
+        def tuple
+          if @lang.list[@md.opt.lng][:n]
+            txt=@lang.list[@md.opt.lng][:n]
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def language_document_char
+        def name
+          'language_document_char'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language_char]}) NOT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document language';}
+        end
+        def tuple
+          #modify check, is now required, SiSUv3d_
+          if defined? @md.opt.lng \
+          and @md.opt.lng=~/\S+/
+            txt=@md.opt.lng
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def language_original
+        def name
+          'language_original'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata original document/text language';}
+        end
+        def tuple
+          if defined? @md.language.original \
+          and @md.language.original=~/\S+/
+            txt=@md.language.original
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def language_original_char
+        def name
+          'language_original_char'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language_char]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document language';}
+        end
+        def tuple
+          if defined? @md.language.original_char \
+          and @md.language.original_char=~/\S+/
+            txt=@md.language.original_char
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% date
+@date:
+ :added_to_site:
+ :available:
+ :created:
+ :issued:
+ :modified:
+ :published:
+ :valid:
+ :translated:
+ :original_publication:
+=end
+      def date_added_to_site
+        def name
+          'date_added_to_site'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+          #"#{name}                DATE,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date added to site';}
+        end
+        def tuple
+          if defined? @md.date.added_to_site \
+          and @md.date.added_to_site=~/\S+/
+            txt=@md.date.added_to_site
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_available
+        def name
+          'date_available'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date added to site [DC]';}
+        end
+        def tuple
+          if defined? @md.date.available \
+          and @md.date.available=~/\S+/
+            txt=@md.date.available
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_created
+        def name
+          'date_created'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date created [DC]';}
+        end
+        def tuple
+          if defined? @md.date.created \
+          and @md.date.created=~/\S+/
+            txt=@md.date.created
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_issued
+        def name
+          'date_issued'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date issued [DC]';}
+        end
+        def tuple
+          if defined? @md.date.issued \
+          and @md.date.issued=~/\S+/
+            txt=@md.date.issued
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_modified
+        def name
+          'date_modified'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date modified [DC]';}
+        end
+        def tuple
+          if defined? @md.date.modified \
+          and @md.date.modified=~/\S+/
+            txt=@md.date.modified
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_published
+        def name
+          'date_published'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date published [DC7]';}
+        end
+        def tuple
+          if defined? @md.date.published \
+          and @md.date.published=~/\S+/
+            txt=@md.date.published
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_valid
+        def name
+          'date_valid'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date valid [DC]';}
+        end
+        def tuple
+          if defined? @md.date.valid \
+          and @md.date.valid=~/\S+/
+            txt=@md.date.valid
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_translated
+        def name
+          'date_translated'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date translated';}
+        end
+        def tuple
+          if defined? @md.date.translated \
+          and @md.date.translated=~/\S+/
+            txt=@md.date.translated
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_original_publication
+        def name
+          'date_original_publication'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_date_text]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date of original publication';}
+        end
+        def tuple
+          if defined? @md.date.original_publication \
+          and @md.date.original_publication=~/\S+/
+            txt=@md.date.original_publication
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def date_generated
+        def name
+          'date_generated'
+        end
+        def create_column              #choose other representation of time
+          "#{name}                VARCHAR(30) NULL,"
+          #"#{name}                VARCHAR(10) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata date of sisu generation of document, automatically populated';}
+        end
+        def tuple                      #choose other representation of time
+          if defined? @md.generated \
+          and @md.generated.to_s=~/\S+/
+            txt=@md.generated.to_s
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% publisher
+@publisher:
+=end
+      def publisher
+        def name
+          'publisher'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document publisher [DC5]';}
+        end
+        def tuple
+          if defined? @md.publisher \
+          and @md.publisher=~/\S+/
+            txt=@md.publisher
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+##% current
+#    def current_publisher
+#      def name
+#        'current_publisher'
+#      end
+#      def size
+#        10
+#      end
+#      def create_column
+#        "#{name}                VARCHAR(#{current_publisher.size}) NULL,"
+#      end
+#      def tuple
+#        t=if defined? @md.current.publisher \
+#        and @md.current.publisher=~/\S+/
+#          txt=@md.current.publisher
+#          txt=special_character_escape(txt)
+#          "'#{txt}', "
+#        end
+#      end
+#      self
+#    end
+=begin
+#% original
+@original:
+ :publisher:
+ #:date:                                #repeated under date
+ :language:
+ :institution:
+ :nationality:
+ :source:
+=end
+      def original_publisher
+        def name
+          'original_publisher'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original publisher [DC5]';}
+        end
+        def tuple
+          if defined? @md.original.publisher \
+          and @md.original.publisher=~/\S+/
+            txt=@md.original.publisher
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def original_language
+        def name
+          'original_language'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original language';}
+        end
+        def tuple
+          if defined? @md.original.language \
+          and @md.original.language=~/\S+/
+            txt=@md.original.language
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def original_language_char         # consider
+        def name
+          'original_language_char'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language_char]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original language iso character';}
+        end
+        def tuple
+          if defined? @md.original.language_char \
+          and @md.original.language_char=~/\S+/
+            txt=@md.original.language_char
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def original_source
+        def name
+          'original_source'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original source [DC11]';}
+        end
+        def tuple
+          if defined? @md.original.source \
+          and @md.original.source=~/\S+/
+            txt=@md.original.source
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def original_institution
+        def name
+          'original_institution'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_name]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original institution';}
+        end
+        def tuple
+          if defined? @md.original.institution \
+          and @md.original.institution=~/\S+/
+            txt=@md.original.institution
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def original_nationality
+        def name
+          'original_nationality'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_language]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document original nationality';}
+        end
+        def tuple
+          if defined? @md.original.nationality \
+          and @md.original.nationality=~/\S+/
+            txt=@md.original.nationality
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% rights
+@rights:
+ #:copyright:                          #mapped to :text: used where no other copyrights and included in :all:
+ :text:
+ :translation:
+ :illustrations:
+ :photographs:
+ :preparation:
+ :digitization:
+ :audio:
+ :video:
+ :license:
+ :all:
+=end
+      def rights_all
+        def name
+          'rights'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata rights associated with document (composite) [DC15]';}
+        end
+        def tuple
+          if defined? @md.rights.all \
+          and @md.rights.all=~/\S+/
+            txt=@md.rights.all
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_text
+        def name
+          'rights_copyright_text'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_text \
+          and @md.rights.copyright_text=~/\S+/
+            txt=@md.rights.copyright_text
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_translation
+        def name
+          'rights_copyright_translation'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text translation (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_translation \
+          and @md.rights.copyright_translation=~/\S+/
+            txt=@md.rights.copyright_translation
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_illustrations
+        def name
+          'rights_copyright_illustrations'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text illustrations (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_illustrations \
+          and @md.rights.copyright_illustrations=~/\S+/
+            txt=@md.rights.copyright_illustrations
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_photographs
+        def name
+          'rights_copyright_photographs'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text photographs (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_photographs \
+          and @md.rights.copyright_photographs=~/\S+/
+            txt=@md.rights.copyright_photographs
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_preparation
+        def name
+          'rights_copyright_preparation'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text preparation (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_preparation \
+          and @md.rights.copyright_preparation=~/\S+/
+            txt=@md.rights.copyright_preparation
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_digitization
+        def name
+          'rights_copyright_digitization'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text digitization (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_digitization \
+          and @md.rights.copyright_digitization=~/\S+/
+            txt=@md.rights.copyright_digitization
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_audio
+        def name
+          'rights_copyright_audio'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text audio (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_audio \
+          and @md.rights.copyright_audio=~/\S+/
+            txt=@md.rights.copyright_audio
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_copyright_video
+        def name
+          'rights_copyright_video'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata copyright associated for document text video (if any)';}
+        end
+        def tuple
+          if defined? @md.rights.copyright_video \
+          and @md.rights.copyright_video=~/\S+/
+            txt=@md.rights.copyright_video
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def rights_license
+        def name
+          'rights_license'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata license granted for use of document if any)';}
+        end
+        def tuple
+          if defined? @md.rights.license \
+          and @md.rights.license=~/\S+/
+            txt=@md.rights.license
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% identifier
+@identifier:
+ :oclc:
+ :isbn:
+=end
+      def identifier_oclc
+        def name
+          'identifier_oclc'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_library]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata identifier document Online Computer Library Center number';}
+        end
+        def tuple
+          if defined? @md.identifier.oclc \
+          and @md.identifier.oclc=~/\S+/
+            txt=@md.identifier.oclc
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def identifier_isbn
+        def name
+          'identifier_isbn'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_small]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata identifier document isbn (if any)';}
+        end
+        def tuple
+          if defined? @md.identifier.isbn \
+          and @md.identifier.isbn=~/\S+/
+            txt=@md.identifier.isbn
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% classify
+@classify:
+ :topic_register:
+ :subject:
+ :keywords:
+ :type:
+ :loc:
+ :dewey:
+=end
+      def classify_topic_register
+        def name
+          'classify_topic_register'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_info_note]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document topic register (semi-structured document subject information)';}
+        end
+        def tuple
+          if defined? @md.classify.topic_register \
+          and @md.classify.topic_register=~/\S+/
+            txt=@md.classify.topic_register
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def classify_subject
+        def name
+          'classify_subject'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_long]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document subject matter [DC3]';}
+        end
+        def tuple
+          if defined? @md.classify.subject \
+          and @md.classify.subject=~/\S+/
+            txt=@md.classify.subject
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def classify_loc
+        def name
+          'classify_loc'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_library]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document Library of Congress';}
+        end
+        def tuple
+          if defined? @md.classify.loc \
+          and @md.classify.loc=~/\S+/
+            txt=@md.classify.loc
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def classify_dewey
+        def name
+          'classify_dewey'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_library]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document Dewey';}
+        end
+        def tuple
+          if defined? @md.classify.dewey \
+          and @md.classify.dewey=~/\S+/
+            txt=@md.classify.dewey
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def classify_keywords
+        def name
+          'classify_keywords'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_long]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document keywords';}
+        end
+        def tuple
+          if defined? @md.classify.keywords \
+          and @md.classify.keywords=~/\S+/
+            txt=@md.classify.keywords
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% notes
+@notes:
+ :abstract:
+ :description:
+ :comment:
+ :coverage:
+ :relation:
+ :format:
+ :history:
+ :prefix:
+ :prefix_a:
+ :prefix_b:
+ :suffix:
+=end
+      def notes_abstract
+        def name
+          'notes_abstract'
+        end
+        def create_column
+          "#{name}                     TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes abstract';}
+        end
+        def tuple
+          if defined? @md.notes.abstract \
+          and @md.notes.abstract=~/\S+/
+            txt=@md.notes.abstract
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_description
+        def name
+          'notes_description'
+        end
+        def create_column
+          "#{name}                    TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes description [DC4]';}
+        end
+        def tuple
+          if defined? @md.notes.description \
+          and @md.notes.description=~/\S+/
+            txt=@md.notes.description
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_comment
+        def name
+          'notes_comment'
+        end
+        def create_column
+          "#{name}                       TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes comment';}
+        end
+        def tuple
+          if defined? @md.notes.comment \
+          and @md.notes.comment=~/\S+/
+            txt=@md.notes.comment
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_coverage
+        def name
+          'notes_coverage'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_short]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document coverage [DC14]';}
+        end
+        def tuple
+          if defined? @md.classify.coverage \
+          and @md.classify.coverage=~/\S+/
+            txt=@md.classify.coverage
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_relation
+        def name
+          'notes_relation'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_short]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document relation [DC13]';}
+        end
+        def tuple
+          if defined? @md.classify.relation \
+          and @md.classify.relation=~/\S+/
+            txt=@md.classify.relation
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_history   #check, consider removal
+        def name
+          'notes_history'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_long]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes history';}
+        end
+        def tuple
+          if defined? @md.notes.history \
+          and @md.notes.history=~/\S+/
+            txt=@md.notes.history
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_type #check
+        def name
+          'notes_type'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_long]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata notes document type [DC8]';}
+        end
+        def tuple
+          if defined? @md.notes.type \
+          and @md.notes.type=~/\S+/
+            txt=@md.notes.type
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_format
+        def name
+          'notes_format'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_txt_long]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata classify document format [DC9]';}
+        end
+        def tuple
+          if defined? @md.classify.format \
+          and @md.classify.format=~/\S+/
+            txt=@md.classify.format
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_prefix
+        def name
+          'notes_prefix'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes prefix';}
+        end
+        def tuple
+          if defined? @md.notes.prefix \
+          and @md.notes.prefix=~/\S+/
+            txt=@md.notes.prefix
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_prefix_a
+        def name
+          'notes_prefix_a'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes prefix_a';}
+        end
+        def tuple
+          if defined? @md.notes.prefix_a \
+          and @md.notes.prefix_a=~/\S+/
+            txt=@md.notes.prefix_a
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_prefix_b
+        def name
+          'notes_prefix_b'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes prefix_b';}
+        end
+        def tuple
+          if defined? @md.notes.prefix_b \
+          and @md.notes.prefix_b=~/\S+/
+            txt=@md.notes.prefix_b
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def notes_suffix
+        def name
+          'notes_suffix'
+        end
+        def create_column                # keep text
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document notes suffix';}
+        end
+        def tuple
+          if defined? @md.notes.suffix \
+          and @md.notes.suffix=~/\S+/
+            txt=@md.notes.suffix
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% src
+=end
+      def src_filename
+        def name
+          'src_filename'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_filename]}) NOT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'sisu markup source text filename';}
+        end
+        def tuple
+          if defined? @md.fns \
+          and @md.fns=~/\S+/
+            txt=@md.fns
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def src_fingerprint
+        def name
+          'src_fingerprint' #hash/digest, sha512, sha256 or md5
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_digest]}) NULL,"
+          #"#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'sisu markup source text fingerprint, hash digest sha512, sha256 or md5';}
+        end
+        def tuple
+          if defined? @md.dgst \
+          and @md.dgst.is_a?(Array) \
+          and @md.dgst[1]=~/\S+/
+            txt=@md.dgst[1]
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def src_filesize
+        def name
+          'src_filesize'
+        end
+        def create_column
+          "#{name}                VARCHAR(#{Db[:col_filesize]}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'sisu markup source text file size';}
+        end
+        def tuple
+         if defined? @md.filesize \
+         and @md.filesize=~/\S+/
+           txt=@md.filesize
+           txt=special_character_escape(txt)
+           ["#{name}, ","'#{txt}', "]
+         else ['','']
+         end
+        end
+        self
+      end
+      def src_word_count
+        def name
+          'src_word_count'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'sisu markup source text word count';}
+        end
+        def tuple
+          if defined? @md.wc_words \
+          and @md.wc_words.to_s=~/\S+/
+            txt=@md.wc_words
+            txt=special_character_escape(txt)
+            ["#{name}, ","'#{txt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def src_txt                      # consider naming sisusrc
+        def name
+          'src_text'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'sisu markup source text (if shared)';}
+        end
+        def tuple
+          if ((@md.opt.act[:psql_import][:set]==:on \
+          || @md.opt.act[:psql_update][:set]==:on) \
+          or (@md.opt.act[:sqlite_import][:set]==:on \
+          || @md.opt.act[:sqlite_update][:set]==:on)) \
+          and FileTest.exist?(@md.fns)
+            ["#{name}, ","'#{@sisutxt}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+=begin
+#% misc
+@links:
+=end
+      def fulltext
+        def name
+          'fulltext'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+            IS 'document full text clean, searchable';}
+        end
+        def tuple
+          if ((@md.opt.act[:psql_import][:set]==:on \
+          || @md.opt.act[:psql_update][:set]==:on) \
+          or (@md.opt.act[:sqlite_import][:set]==:on \
+          || @md.opt.act[:sqlite_update][:set]==:on)) \
+          and  FileTest.exist?(@md.fns)
+            ["#{name}, ","'#{@fulltext}', "]
+          else ['','']
+          end
+        end
+        self
+      end
+      def links
+        def name
+          'links'
+        end
+        def create_column
+          "#{name}                TEXT NULL,"
+          #"#{name}                 VARCHAR(#{links.size}) NULL,"
+        end
+        def column_comment
+          %{COMMENT ON COLUMN metadata_and_text.#{name}
+           IS 'metadata document links';}
+        end
+        #def tuple
+        #  #BUG HERE - links is an array of paired values :say :url
+        #  if defined? @md.links \
+        #  and @md.links=~/\S+/
+        #    txt=@md.links
+        #    txt=special_character_escape(txt)
+        #    ["#{name}, ","'#{txt}', "]
+        #  else ['','']
+        #  end
+        #end
+        self
+      end
+      self
+    end
+  end
+  class ColumnSize
+    def document_clean # restriction not necessary
+      60000
+    end
+    def document_body
+      16000
+    end
+    def document_seg
+      120
+    end
+    def document_seg_full
+      120
+    end
+    def endnote_clean # restriction not necessary
+      60000
+    end
+    def endnote_body
+      16000
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** db_indexes.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_indexes.rb"
+# <>
+module SiSU_DbIndex
+  class Index                                           # create documents Indexes def initialize(opt,conn='',sql_type)
+    def initialize(opt,conn,file,sql_type)
+      @opt,@conn,@file,@sql_type=opt,conn,file,sql_type
+    end
+    def create_indexes                                                           # check added from pg not tested
+      def conn_execute_sql_pg(conn,sql)
+        conn.exec_params(sql)
+      end
+      def conn_execute_sql_sqlite(conn,sql)
+        conn.execute(sql)
+      end
+      def conn_execute_sql(conn,sql)
+        if @sql_type==:pg
+          conn_execute_sql_pg(conn,sql)
+        elsif @sql_type==:sqlite
+          conn_execute_sql_sqlite(conn,sql)
+        else
+        end
+      end
+      def conn_execute_array(sql_arr)
+        begin
+          @conn.transaction do |conn|
+            sql_arr.each do |sql|
+              conn_execute_sql(conn,sql)
+            end
+          end
+        rescue
+          if @conn.is_a?(NilClass)
+            errmsg="No sqlite3 connection (check sqlite3 dependencies)"
+            if @opt.act[:no_stop][:set]==:on
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, proceeding without sqlite output (as requested)")
+            else
+              SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                error("#{errmsg}, STOPPING")
+              exit
+            end
+          end
+        end
+      end
+      def base
+        if (@opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          print "\n          create documents common indexes\n"
+        end
+        sql_arr=[
+          %{CREATE INDEX idx_ocn ON doc_objects(ocn);},
+          %{CREATE INDEX idx_digest_clean ON doc_objects(digest_clean);},
+          %{CREATE INDEX idx_digest_all ON doc_objects(digest_all);},
+          %{CREATE INDEX idx_lev0 ON doc_objects(lev0);},
+          %{CREATE INDEX idx_lev1 ON doc_objects(lev1);},
+          %{CREATE INDEX idx_lev2 ON doc_objects(lev2);},
+          %{CREATE INDEX idx_lev3 ON doc_objects(lev3);},
+          %{CREATE INDEX idx_lev4 ON doc_objects(lev4);},
+          %{CREATE INDEX idx_lev5 ON doc_objects(lev5);},
+          %{CREATE INDEX idx_lev6 ON doc_objects(lev6);},
+          %{CREATE INDEX idx_endnote_nr ON endnotes(nr);},
+          %{CREATE INDEX idx_digest_en ON endnotes(digest_clean);},
+          %{CREATE INDEX idx_endnote_nr_asterisk ON endnotes_asterisk(nr);},
+          %{CREATE INDEX idx_endnote_asterisk ON endnotes_asterisk(clean);},
+          %{CREATE INDEX idx_digest_en_asterisk ON endnotes_asterisk(digest_clean);},
+          %{CREATE INDEX idx_endnote_nr_plus ON endnotes_plus(nr);},
+          %{CREATE INDEX idx_endnote_plus ON endnotes_plus(clean);},
+          %{CREATE INDEX idx_digest_en_plus ON endnotes_plus(digest_clean);},
+          %{CREATE INDEX idx_title ON metadata_and_text(title);},
+          %{CREATE INDEX idx_author ON metadata_and_text(creator_author);},
+          %{CREATE INDEX idx_filename ON metadata_and_text(src_filename);},
+          %{CREATE INDEX idx_language ON metadata_and_text(language_document_char);},
+          %{CREATE INDEX idx_topics ON metadata_and_text(classify_topic_register)},
+        ]
+        conn_execute_array(sql_arr)
+      end
+      def text
+        if (@opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          print "\n          create documents TEXT indexes\n"
+        end
+        sql_arr=[
+          %{CREATE INDEX idx_clean ON doc_objects(clean);},
+          %{CREATE INDEX idx_endnote ON endnotes(clean);}
+        ]
+        conn_execute_array(sql_arr)
+      end
+      base
+      @opt.act[:psql][:set]==:on ? '' : text
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* db_tests.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/db_tests.rb"
+# <>
+module SiSU_DbTests
+  class Test
+    def initialize(info,opt)
+      @ck,@opt=info,opt
+      unless @opt.act[:quiet][:set]==:on
+        puts @ck.tp[:fns]  if @ck.tp[:fns] and not @ck.tp[:fns].empty?
+        puts @ck.tp[:title] if @ck.tp[:title] and not @ck.tp[:title].empty?
+        puts @ck.tp[:creator] if @ck.tp[:creator] and not @ck.tp[:creator].empty?
+      end
+    end
+    def verify
+      unless @opt.act[:quiet][:set]==:on
+        puts @ck.tp[:fns].length.to_s                + ' checklength ' + @ck.tp[:fns]                if @ck.tp[:fns]                and @ck.tp[:fns].length                >@ck.lt_filename
+        puts @ck.tp[:title].length.to_s              + ' checklength ' + @ck.tp[:title]              if @ck.tp[:title]              and @ck.tp[:title].length              >@ck.lt_title
+        puts @ck.tp[:subtitle].length.to_s           + ' checklength ' + @ck.tp[:subtitle]           if @ck.tp[:subtitle]           and @ck.tp[:subtitle].length           >@ck.lt_subtitle
+        puts @ck.tp[:creator].length.to_s            + ' checklength ' + @ck.tp[:creator]            if @ck.tp[:creator]            and @ck.tp[:creator].length            >@ck.lt_creator
+        puts @ck.tp[:author_title].length.to_s       + ' checklength ' + @ck.tp[:author_title]       if @ck.tp[:author_title]       and @ck.tp[:author_title].length       >@ck.lt_author_title
+        puts @ck.tp[:illustrator].length.to_s        + ' checklength ' + @ck.tp[:illustrator]        if @ck.tp[:illustrator]        and @ck.tp[:illustrator].length        >@ck.lt_illustrator
+        puts @ck.tp[:translator].length.to_s         + ' checklength ' + @ck.tp[:translator]         if @ck.tp[:translator]         and @ck.tp[:translator].length         >@ck.lt_translator
+        puts @ck.tp[:prepared_by].length.to_s        + ' checklength ' + @ck.tp[:prepared_by]        if @ck.tp[:prepared_by]        and @ck.tp[:prepared_by].length        >@ck.lt_prepared_by
+        puts @ck.tp[:digitized_by].length.to_s       + ' checklength ' + @ck.tp[:digitized_by]       if @ck.tp[:digitized_by]       and @ck.tp[:digitized_by].length       >@ck.lt_digitized_by
+        puts @ck.tp[:subject].length.to_s            + ' checklength ' + @ck.tp[:subject]            if @ck.tp[:subject]            and @ck.tp[:subject].length            >@ck.lt_subject
+        puts @ck.tp[:description].length.to_s        + ' checklength ' + @ck.tp[:description]        if @ck.tp[:description]        and @ck.tp[:description].length        >@ck.lt_description
+        puts @ck.tp[:publisher].length.to_s          + ' checklength ' + @ck.tp[:publisher]          if @ck.tp[:publisher]          and @ck.tp[:publisher].length          >@ck.lt_publisher
+        puts @ck.tp[:contributor].length.to_s        + ' checklength ' + @ck.tp[:contributor]        if @ck.tp[:contributor]        and @ck.tp[:contributor].length        >@ck.lt_contributor
+        puts @ck.tp[:date].length.to_s               + ' checklength ' + @ck.tp[:date]               if @ck.tp[:date]               and @ck.tp[:date].length               >@ck.lt_date
+        puts @ck.tp[:date_created].length.to_s       + ' checklength ' + @ck.tp[:date_created]       if @ck.tp[:date_created]       and @ck.tp[:date_created].length       >@ck.lt_date
+        puts @ck.tp[:date_issued].length.to_s        + ' checklength ' + @ck.tp[:date_issued]        if @ck.tp[:date_issued]        and @ck.tp[:date_issued].length        >@ck.lt_date
+        puts @ck.tp[:date_valid].length.to_s         + ' checklength ' + @ck.tp[:date_valid]         if @ck.tp[:date_valid]         and @ck.tp[:date_valid].length         >@ck.lt_date
+        puts @ck.tp[:date_available].length.to_s     + ' checklength ' + @ck.tp[:date_available]     if @ck.tp[:date_available]     and @ck.tp[:date_available].length     >@ck.lt_date
+        puts @ck.tp[:date_modified].length.to_s      + ' checklength ' + @ck.tp[:date_modified]      if @ck.tp[:date_modified]      and @ck.tp[:date_modified].length      >@ck.lt_date
+        puts @ck.tp[:date_translated].length.to_s    + ' checklength ' + @ck.tp[:date_translated]    if @ck.tp[:date_translated]    and @ck.tp[:date_translated].length    >@ck.lt_date
+        puts @ck.tp[:date_added_to_site].length.to_s + ' checklength ' + @ck.tp[:date_added_to_site] if @ck.tp[:date_added_to_site] and @ck.tp[:date_added_to_site].length >@ck.lt_date
+        puts @ck.tp[:type].length.to_s               + ' checklength ' + @ck.tp[:type]               if @ck.tp[:type]               and @ck.tp[:type].length               >@ck.lt_type
+        puts @ck.tp[:format].length.to_s             + ' checklength ' + @ck.tp[:format]             if @ck.tp[:format]             and @ck.tp[:format].length             >@ck.lt_format
+        puts @ck.tp[:identifier].length.to_s         + ' checklength ' + @ck.tp[:identifier]         if @ck.tp[:identifier]         and @ck.tp[:identifier].length         >@ck.lt_identifier
+        puts @ck.tp[:source].length.to_s             + ' checklength ' + @ck.tp[:source]             if @ck.tp[:source]             and @ck.tp[:source].length             >@ck.lt_source
+        puts @ck.tp[:language].length.to_s           + ' checklength ' + @ck.tp[:language]           if @ck.tp[:language]           and @ck.tp[:language].length           >@ck.lt_language
+        puts @ck.tp[:language_original].length.to_s  + ' checklength ' + @ck.tp[:language_original]  if @ck.tp[:language_original]  and @ck.tp[:language_original].length  >@ck.lt_language_original
+        puts @ck.tp[:relation].length.to_s           + ' checklength ' + @ck.tp[:relation]           if @ck.tp[:relation]           and @ck.tp[:relation].length           >@ck.lt_relation
+        puts @ck.tp[:coverage].length.to_s           + ' checklength ' + @ck.tp[:coverage]           if @ck.tp[:coverage]           and @ck.tp[:coverage].length           >@ck.lt_coverage
+        puts @ck.tp[:rights].length.to_s             + ' checklength ' + @ck.tp[:rights]             if @ck.tp[:rights]             and @ck.tp[:rights].length             >@ck.lt_rights
+        puts @ck.tp[:copyright].length.to_s          + ' checklength ' + @ck.tp[:copyright]          if @ck.tp[:copyright]          and @ck.tp[:copyright].length          >@ck.lt_copyright
+        puts @ck.tp[:owner].length.to_s              + ' checklength ' + @ck.tp[:owner]              if @ck.tp[:owner]              and @ck.tp[:owner].length              >@ck.lt_owner
+        puts @ck.tp[:keywords].length.to_s           + ' checklength ' + @ck.tp[:keywords]           if @ck.tp[:keywords]           and @ck.tp[:keywords].length           >@ck.lt_keywords
+        puts @ck.tp[:abstract].length.to_s           + ' checklength ' + @ck.tp[:abstract]           if @ck.tp[:abstract]           and @ck.tp[:abstract].length           >@ck.lt_abstract
+        puts @ck.tp[:comment].length.to_s            + ' checklength ' + @ck.tp[:comment]            if @ck.tp[:comment]            and @ck.tp[:comment].length            >@ck.lt_comment
+        puts @ck.tp[:loc].length.to_s                + ' checklength ' + @ck.tp[:loc]                if @ck.tp[:loc]                and @ck.tp[:loc].length                >@ck.lt_loc
+        puts @ck.tp[:dewey].length.to_s              + ' checklength ' + @ck.tp[:dewey]              if @ck.tp[:dewey]              and @ck.tp[:dewey].length              >@ck.lt_dewey
+        puts @ck.tp[:isbn].length.to_s               + ' checklength ' + @ck.tp[:isbn]               if @ck.tp[:isbn]               and @ck.tp[:isbn].length               >@ck.lt_isbn
+        puts @ck.tp[:pg].length.to_s                 + ' checklength ' + @ck.tp[:pg]                 if @ck.tp[:pg]                 and @ck.tp[:pg].length                 >@ck.lt_pg
+        puts @ck.tp[:topic_register].length.to_s     + ' checklength ' + @ck.tp[:topic_register]     if @ck.tp[:topic_register]     and @ck.tp[:topci_register].length     >@ck.lt_topic_register
+        puts @ck.tp[:date]                                                                           if @ck.tp[:date] and not @ck.tp[:date].empty? and @ck.tp[:date] !~/\d\d-\d\d-\d\d/
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* document header
+
+#+NAME: sisu_document_header
+#+BEGIN_SRC text
+encoding: utf-8
+- Name: SiSU
+
+  - Description: documents, structuring, processing, publishing, search
+    db sql
+
+  - Author: Ralph Amissah
+    
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+    All Rights Reserved.
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/digests.org b/org/digests.org
new file mode 100644
index 00000000..7107f53f
--- /dev/null
+++ b/org/digests.org
@@ -0,0 +1,330 @@
+-*- mode: org -*-
+#+TITLE:       sisu digests
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:digests:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* digests.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/digests.rb"
+# <>
+module SiSU_DigestView
+  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
+  require_relative 'prog_text_translation'              # prog_text_translation.rb
+  require_relative 'shared_markup_alt.rb'               # shared_markup_alt.rb
+  class Source
+    @@dg=nil
+    def initialize(opt)
+      @opt=opt
+      @fnb=@opt.fnb
+      @@endnotes_para=[]
+      @@dg=nil
+      @dg=@@dg ||=SiSU_Env::InfoEnv.new.digest(opt).type
+      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
+    end
+    def read
+      begin
+        @env,@md,@ao_array=@particulars.env,@particulars.md,@particulars.ao_array
+        unless @opt.act[:quiet][:set]==:on
+          tool=(@opt.act[:verbose][:set]==:on \
+          || @opt.act[:verbose_plus][:set]==:on \
+          || @opt.act[:maintenance][:set]==:on) \
+          ? "#{@env.program.text_editor} file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}"
+          : "[#{@opt.f_pth[:lng_is]}] #{@opt.fno}"
+          (@opt.act[:verbose][:set]==:on \
+          || @opt.act[:verbose_plus][:set]==:on \
+          || @opt.act[:maintenance][:set]==:on) \
+          ? SiSU_Screen::Ansi.new(
+              @opt.act[:color_state][:set],
+              "Document #{@dg} Digests",
+              tool
+            ).green_hi_blue
+          : SiSU_Screen::Ansi.new(
+              @opt.act[:color_state][:set],
+              "Document #{@dg} Digests",
+              tool
+            ).green_title_hi
+          if @opt.act[:verbose_plus][:set]==:on \
+          or @opt.act[:maintenance][:set]==:on
+            SiSU_Screen::Ansi.new(
+              @opt.act[:color_state][:set],
+              @opt.fns,
+              "file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}"
+            ).flow
+          end
+        end
+        if SiSU_Env::SystemCall.new.openssl
+          SiSU_DigestView::Source::Scroll.new(@particulars).songsheet
+        else
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).error('*EXITED* hash digests will not run without openssl')
+        end
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    private
+    class Scroll  0
+        end
+        ao_structure_summary("objects (ocn) = #{ocn}\n")
+        ao_structure_summary("endnotes      = #{endnotes}\n")
+        ao_structure_summary("  [*] number of headers (@) and of each heading level (:A to :D and 1 to 3)\n")
+      end
+      def supplementary
+        if defined? @md.sc_number \
+        and @md.sc_number
+          rcinfo("------------\n")
+          rcinfo("source control information\n")
+          rcinfo("  (the following information while not important for document content certification\n   may help the publisher in locating the version referred to)\n")
+          rcinfo("  rcs version number:            #{@md.sc_number}\n")
+          if defined? @md.sc_date \
+          and @md.sc_date
+            rcinfo("  rcs date:                      #{@md.sc_date}\n")
+          end
+          if defined? @md.sc_time \
+          and @md.sc_time
+            rcinfo("  rcs time:                      #{@md.sc_time}\n")
+          end
+        end
+        rcinfo("------------\n")
+        rcinfo("Note: the time generated related fields (text and digests) will vary between otherwise identical document outputs\n")
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* document header
+
+#+NAME: sisu_document_header
+#+BEGIN_SRC text
+encoding: utf-8
+- Name: SiSU
+
+  - Description: documents, structuring, processing, publishing, search
+    digests
+
+  - Author: Ralph Amissah
+    
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+    All Rights Reserved.
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/env.org b/org/env.org
new file mode 100644
index 00000000..fafc90ef
--- /dev/null
+++ b/org/env.org
@@ -0,0 +1,8610 @@
+-*- mode: org -*-
+#+TITLE:       sisu environment
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:se:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* sisu environment
+** se.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se.rb"
+# <>
+@@cX=nil
+module SiSU_Env
+  require_relative 'constants'                         # constants.rb
+  require_relative 'utils'                             # utils.rb
+  require_relative 'se_date'                           # se_date.rb
+  require_relative 'se_info_system'                    # se_info_system.rb
+  require_relative 'se_load'                           # se_load.rb
+  require_relative 'se_get_init'                       # se_get_init.rb
+  require_relative 'se_envcall'                        # se_envcall.rb
+  require_relative 'se_programs'                       # se_programs.rb
+  require_relative 'se_standardise_lang'               # se_standardise_lang.rb
+  require_relative 'se_info_env'                       # se_info_env.rb
+  require_relative 'se_processing'                     # se_processing.rb
+  require_relative 'se_filemap'                        # se_filemap.rb
+  require_relative 'se_file_op'                        # se_file_op.rb
+  require_relative 'se_cleanoutput'                    # se_cleanoutput.rb
+  require_relative 'se_remotes'                        # se_remotes.rb
+  require_relative 'se_version'                        # se_version.rb
+  require_relative 'se_db'                             # se_db.rb
+  require_relative 'se_css'                            # se_css.rb
+  require_relative 'se_clear'                          # se_clear.rb
+  require_relative 'se_createsite'                     # se_createsite.rb
+  require_relative 'se_info_port'                      # se_info_port.rb
+  begin
+    require 'singleton'
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton or fileutils NOT FOUND (LoadError)')
+  end
+  @@noyaml=false
+  class InfoDate < SiSU_Info_Date::InfoDate                # se_date.rb
+  end
+  class InfoSystemGen < SiSU_Info_Sys_Gen::InfoSystemGen   # se_info_system.rb
+  end
+  class InfoSystem < SiSU_Info_Sys::InfoSystem             # se_info_system.rb
+  end
+  class Load < SiSU_Load::Load                             # se_load.rb
+  end
+  class GetInit < SiSU_Get_Init::GetInit                   # se_get_init.rb
+  end
+  class EnvCall < SiSU_Env_Call::EnvCall                   # se_envcall.rb
+  end
+  class SystemCall < SiSU_Sys_Call::SystemCall             # se_programs.rb
+  end
+  class StandardiseLanguage < SiSU_Standardise_Lang::StandardiseLanguage # se_standardise_lang.rb
+  end
+  class InfoEnv < SiSU_Info_Env::InfoEnv                   # se_info_env.rb
+  end
+  class InfoProcessingFlag < SiSU_Info_Processing_Flag::InfoProcessingFlag # se_processing.rb
+  end
+  class InfoSettings < SiSU_Info_Set::InfoSettings         # se_programs.rb
+  end
+  class FileMap < SiSU_File_Map::FileMap                   # se_filemap.rb
+  end
+  class CleanOutput < SiSU_Clean_Output::CleanOutput       # se_cleanoutput.rb
+  end
+  class InfoRemoteHost < SiSU_Info_Remote_Host::InfoRemoteHost # se_remotes.rb
+  end
+  class InfoRemote < SiSU_Info_Remote::InfoRemote          # se_remotes.rb
+  end
+  class InfoVersion < SiSU_Info_Version::InfoVersion       # se_version.rb
+  end
+  class InfoAbout < SiSU_Info_About::InfoAbout             # se_version.rb
+  end
+  class InfoFile < SiSU_Info_File::InfoFile                # se_file_op.rb
+  end
+  class ProcessingSettings < SiSU_Processing_Settings::ProcessingSettings # se_processing.rb
+  end
+  class InfoDb < SiSU_Info_Db::InfoDb                      # se_db.rb
+  end
+  class DbOp < SiSU_Db_Op::DbOp                            # se_db.rb
+  end
+  class FileOp < SiSU_File_Op::FileOp                      # se_file_op.rb
+  end
+  class FilenameLanguageCodeInsert < SiSU_Filename_Lang::FilenameLanguageCodeInsert # se_file_op.rb
+  end
+  class CreateFile < SiSU_Create_File::CreateFile          # se_file_op.rb
+  end
+  class Clear < SiSU_Clear::Clear                          # se_clear.rb
+  end
+  class InfoPort < SiSU_Info_Port::InfoPort                # se_info_port.rb
+  end
+  class InfoProgram < SiSU_Info_Program::InfoProgram       # se_programs.rb
+  end
+  class CSS_Default < SiSU_CSS::CSS_Default                # se_css.rb
+  end
+  class CSS_Select < SiSU_CSS::CSS_Select                  # se_css.rb
+  end
+  class CSS_Stylesheet < SiSU_CSS::CSS_Stylesheet          # se_css.rb
+  end
+  class CreateSite < SiSU_Create_Site::CreateSite          # se_createsite.rb
+  end
+end
+module SiSU_Screen
+  require_relative 'utils_screen_text_color'               # utils_screen_text_color.rb
+end
+module SiSU_Errors
+  require_relative 'errors'                             # errors.rb
+end
+__END__
+#+END_SRC
+
+** se_cleanoutput.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_cleanoutput.rb"
+# <>
+module SiSU_Clean_Output
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class CleanOutput
+    begin
+      require 'fileutils'
+        include FileUtils::Verbose
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('fileutils NOT FOUND (LoadError)')
+    end
+    def initialize(opt)
+      @opt=opt
+      z=SiSU_Env::FileMap.new(opt)
+      zap=z.local_sisu_source
+      if opt.cmd =~ /h/i
+        zap=Dir.glob(zap).join(' ')
+        @zap=if opt.cmd !~ /w/
+          zap.gsub(/#{@source_path}\/concordance.html/,'')
+        else zap
+        end
+      end
+      @env=SiSU_Env::InfoEnv.new
+    end
+    def zap
+      def deletion(fn)
+        if FileTest.file?(fn)==true
+          File.delete(fn)
+          tell=SiSU_Screen::Ansi.new(@opt.cmd,@opt.fns, 'remove: ' + fn)
+          tell.warn unless @opt.cmd =~/q/
+        end
+      end
+      def remove_output
+        if @opt.act[:maintenance][:set] == :on
+          m=InfoFile.new(@opt.fnc)
+          tell=SiSU_Screen::Ansi.new(
+            @opt.cmd,@opt.fns,
+            'remove maintenance files from: ' + @env.processing_path.ao
+          )
+          tell.warn unless @opt.cmd =~/q/
+          deletion(m.marshal.ao_content)
+          deletion(m.marshal.ao_idx_sst_rel_html_seg)
+          deletion(m.ao_idx_sst_rel)
+          deletion(m.ao_idx_html)
+          deletion(m.ao_idx_xhtml)
+          deletion(m.ao_metadata)
+          deletion(m.ao_map_nametags)
+          deletion(m.ao_map_ocn_htmlseg)
+          deletion(m.html_tune)
+        end
+        md=SiSU_Param::Parameters.new(@opt).get
+        f=SiSU_Env::FileOp.new(md)
+        deletion(f.place_file.html_segtoc.dir)
+        deletion(f.place_file.html_scroll.dir)
+        deletion(f.place_file.html_book_index.dir)
+        deletion(f.place_file.html_concordance.dir)
+        deletion(f.place_file.epub.dir)
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_letter}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_l_letter}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_a4}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_l_a4}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_a5}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_l_a5}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_b5}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_l_b5}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_legal}")
+        deletion("#{f.output_path.pdf.dir}/#{f.base_filename.pdf_p_legal}")
+        deletion(f.place_file.odt.dir)
+        deletion(f.place_file.xhtml.dir)
+        deletion(f.place_file.xml_sax.dir)
+        deletion(f.place_file.xml_dom.dir)
+        deletion(f.place_file.xml_scaffold_structure_sisu.dir)
+        deletion(f.place_file.xml_scaffold_structure_collapse.dir)
+        deletion(f.place_file.info.dir)
+        deletion(f.place_file.manpage.dir)
+        deletion(f.place_file.sqlite_discrete.dir)
+        deletion(f.place_file.txt.dir)
+        deletion(f.place_file.hash_digest.dir)
+        deletion(f.place_file.manifest.dir)
+        deletion(f.place_file.qrcode_md.dir)
+        deletion(f.place_file.qrcode_title.dir)
+        deletion(f.place_file.src.dir)
+        deletion(f.place_file.sisupod.dir)
+      end
+      self
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_clear.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_clear.rb"
+# <>
+module SiSU_Clear
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  class Clear < SiSU_Info_Env::InfoEnv                     # se_info_env.rb
+    #todo unify with FileOp
+    def initialize(cmd,fns,operation='')
+      @cmd=cmd
+      begin
+        super(fns)
+        @env=SiSU_Env::InfoEnv.new(fns)
+        SiSU_Env::InfoVersion.instance
+        if operation.class.inspect =~/SiSU_Param/
+          @md=operation
+        end
+        case operation #watch
+        when /pdf/                 then @env_out=''
+        when /sql/
+        when /xml|plaintext|ascii/ then @env_out=@env.path.output + @fnb #check change of name to plaintext from ascii
+        else
+          if defined? @md.sfx_src \
+          and @md.sfx_src =~/ss[ftsumc]/
+            @env_out_root=@env.path.output
+            @env_out="#{@env.path.output}/#{@fnb}"
+            @@publisher='SiSU http://www.jus.uio.no/sisu'
+            @env_pdf="#{@env_out_root}/pdf"
+          end
+        end
+      rescue
+        SiSU_Screen::Ansi.new(@cmd,$!,$@).rescue do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def param_instantiate
+      @cX||=SiSU_Screen::Ansi.new(@cmd)
+      @@date=SiSU_Env::InfoDate.new
+      @@publisher='SiSU scribe'
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_createsite.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_createsite.rb"
+# <>
+module SiSU_Create_Site
+  require_relative 'constants'                             # constants.rb
+  require_relative 'html_parts'                            # html_parts.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'utils_screen_text_color'               # utils_screen_text_color.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  begin
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('fileutils NOT FOUND (LoadError)')
+  end
+  class CreateSite < SiSU_Info_Env::InfoEnv                # se_info_env.rb
+    require_relative 'css'                                 # css.rb
+      include SiSU_Style
+    def initialize(opt)
+      @opt=opt
+      @env=SiSU_Env::InfoEnv.new
+      @init=SiSU_Env::GetInit.new
+      @home,@pwd=ENV['HOME'],ENV['PWD'] #@pwd=Dir.pwd
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @home_set=SiSU_Proj_HTML::Home.new
+    end
+    def create_default_sisu_homepage(action=:none)
+      if action==:none
+        puts %{  place your homepages in directory:\n    "#{@env.path.rc}/home/*.html"\n  (no action taken)}
+      else # turned off, unless something other than :none passed
+        puts %{  place your homepages in directory:\n    "#{@env.path.rc}/home/*.html"\n  (in order to replace default sisu homepage)}
+        filename_homepage=
+          @env.path.webserv + '/' \
+          + @env.path.base_markup_dir_stub + '/index.html'
+        filename_home_toc=
+          @env.path.webserv + '/' \
+          + @env.path.base_markup_dir_stub + '/toc.html'
+        file_homepage=File.new(filename_homepage,'w')
+        file_home_toc=File.new(filename_home_toc,'w')
+        file_homepage << @home_set.homepage
+        file_home_toc << @home_set.homepage
+        file_homepage.close
+        file_home_toc.close
+      end
+    end
+    def homepage
+      home_pages_manually_created=Dir.glob("#{@env.path.rc}/home/*.html")
+      FileUtils::mkdir_p("#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}") \
+        unless FileTest.directory?("#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}")
+      if home_pages_manually_created.length > 0
+        home_pages_manually_created.each do |homepage|
+          FileUtils.cp(homepage,"#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}")
+        end
+      else
+        create_default_sisu_homepage(:none) # :default
+      end
+    end
+    def cp_images(src_path,dest_path)
+      if FileTest.directory?(src_path)
+        FileUtils::cd(src_path)
+        source=Dir.glob("*.{png,jpg,gif,ico}")
+        FileUtils::mkdir_p(dest_path) unless FileTest.directory?(dest_path)
+        FileUtils::chmod(0755,dest_path)
+        source.each do |i|
+          if FileTest.file?(i)
+            FileUtils::cp(i,"#{dest_path}/#{i}")
+            FileUtils::chmod(0644,"#{dest_path}/#{i}")
+          else STDERR.puts %{\t*WARN* did not find image - "#{i}" [#{__FILE__}:#{__LINE__}]}
+          end
+        end
+        FileUtils::cd(@pwd)
+      else STDERR.puts %{\t*WARN* did not find - #{src_path} [#{__FILE__}:#{__LINE__}]}
+      end
+    end
+    def cp_local_images
+      src=@pwd + '/_sisu/image'
+      dest=
+        @env.path.webserv + '/' \
+        + @env.path.base_markup_dir_stub + '/_sisu/image'
+      cp_images(src,dest) if FileTest.directory?(src)
+    end
+    def cp_external_images
+      src=@env.processing_path.processing + '/' \
+      + 'external_document/image'
+      dest=
+        @env.path.webserv + '/' \
+        + @env.path.base_markup_dir_stub + '/' \
+        + '_sisu/image_external'
+      if FileTest.directory?(src)
+        cp_images(src,dest) if FileTest.directory?(src)
+      end
+    end
+    def cp_webserver_images
+      src=@env.path.image_source
+      dest_arr=[
+        "#{@env.path.webserv}/_sisu/image",
+        "#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/image",
+      ]
+      dest_arr.each do |dest|
+        cp_images(src,dest) if FileTest.directory?(src)
+      end
+    end
+    def cp_webserver_images_local      #this should not have been necessary
+      src=@env.path.image_source
+      dest=
+        @env.path.webserv + '/' \
+        + @env.path.base_markup_dir_stub + '/' \
+        + '_sisu/image'
+      cp_images(src,dest) if FileTest.directory?(src)
+    end
+    def cp_base_images #fix images
+      src=SiSU_is.path_base_system_data? + '/image'
+      dest_arr=[
+        "#{@env.path.webserv}/_sisu/image_sys",
+        "#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/image_sys"
+      ]
+      dest_arr.each do |dest|
+        cp_images(src,dest) if FileTest.directory?(src)
+      end
+    end
+    def cp_css
+      FileUtils::mkdir_p("#{@env.path.output}/#{@env.path.style}") \
+        unless FileTest.directory?("#{@env.path.output}/#{@env.path.style}")
+      css_path=[
+        '/etc/sisu/css',
+        "#{@home}/.sisu/css",
+        "#{@pwd}/_sisu/css",
+      ] #BROKEN
+      if defined? @rc['permission_set']['css_modify'] \
+      and @rc['permission_set']['css_modify']
+        SiSU_Screen::Ansi.new(
+          @opt.selections.str,
+          "*WARN* modify is css set to: #{@rc['permission_set']['css_modify']}"
+        ).warn if @opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on
+        css_path.each do |x|
+          if FileTest.directory?(x)
+            FileUtils::cd(x)
+            source=Dir.glob("*.{css}")
+            source.each do |i|
+              if FileTest.file?(i)
+                FileUtils::cp(
+                  i,
+                  @env.path.output + '/' + @env.path.style
+                )
+              else STDERR.puts %{\t*WARN* did not find css - "#{i}" [#{__FILE__}:#{__LINE__}]}
+              end
+            end
+            FileUtils::cd(@pwd)
+          end
+        end
+      else
+        SiSU_Screen::Ansi.new(
+          @opt.selections.str,
+          "*WARN* modify css is not set or is set to: false"
+        ).warn if @opt.act[:verbose_plus][:set]==:on \
+        or @opt.act[:maintenance][:set]==:on
+      end
+      fn_css=SiSU_Env::CSS_Default.new
+      css=SiSU_Style::CSS.new
+      path_style="#{@env.path.output}/#{@env.path.style}"
+      FileUtils::mkdir_p(path_style) \
+        unless FileTest.directory?(path_style)
+      if @opt.act[:site_init][:set]==:on \
+      or not FileTest.file?("#{path_style}/#{fn_css.homepage}")
+        style=File.new("#{path_style}/#{fn_css.homepage}",'w')
+        style << css.homepage
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or not FileTest.file?("#{path_style}/#{fn_css.html_tables}")
+        style=File.new("#{path_style}/#{fn_css.html_tables}",'w')
+        style << css.html_tables
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or not FileTest.file?("#{path_style}/#{fn_css.html}")
+        style=File.new("#{path_style}/#{fn_css.html}",'w')
+        style << css.html
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or not FileTest.file?("#{path_style}/#{fn_css.harvest}")
+        style=File.new("#{path_style}/#{fn_css.harvest}",'w')
+        style << css.harvest
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or (@opt.act[:xml_sax][:set]==:on \
+      and not FileTest.file?("#{path_style}/#{fn_css.xml_sax}"))
+        style=File.new("#{path_style}/#{fn_css.xml_sax}",'w')
+        style << css.xml_sax
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or (@opt.act[:xml_dom][:set]==:on \
+      and not FileTest.file?("#{path_style}/#{fn_css.xml_dom}"))
+        style=File.new("#{path_style}/#{fn_css.xml_dom}",'w')
+        style << css.xml_dom
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or (@opt.act[:xml_docbook_book][:set] == :on \
+      and not FileTest.file?("#{path_style}/#{fn_css.xml_docbook}"))
+        style=File.new("#{path_style}/#{fn_css.xml_docbook}",'w')
+        style << css.xml_docbook
+        style.close
+      end
+      if @opt.act[:site_init][:set]==:on \
+      or (@opt.act[:xhtml][:set] == :on \
+      and not FileTest.file?("#{path_style}/#{fn_css.xhtml}"))
+        style=File.new("#{path_style}/#{fn_css.xhtml}",'w')
+        style << css.xhtml
+        style.close
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_css.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_css.rb"
+# <>
+module SiSU_CSS
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class CSS_Default
+    def html
+      'html.css'
+    end
+    def html_tables
+      'html_tables.css'
+    end
+    def xhtml
+      'xhtml.css'
+    end
+    def xml_sax
+      'sax.css'
+    end
+    def xml_dom
+      'dom.css'
+    end
+    def xml_docbook
+      'docbook.css'
+    end
+    def homepage
+      'homepage.css'
+    end
+    def harvest
+      'harvest.css'
+    end
+  end
+  class CSS_Select < SiSU_Info_Env::InfoEnv                # se_info_env.rb
+    def initialize(md)
+      @md=md
+      @env=SiSU_Env::InfoEnv.new('',@md)
+    end
+    def html
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_html.css")
+        @md.doc_css + '_html.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_html.css")
+        @env.path.base_markup_dir_stub + '_html.css'
+      else
+        SiSU_Env::CSS_Default.new.html
+      end
+    end
+    def html_tables
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_html_tables.css")
+        @md.doc_css + '_html_tables.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_html_tables.css")
+        @env.path.base_markup_dir_stub + '_html_tables.css'
+      else SiSU_Env::CSS_Default.new.html_tables
+      end
+    end
+    def xhtml
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_xhtml.css")
+        @md.doc_css + '_xhtml.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_xhtml.css")
+        @env.path.base_markup_dir_stub + '_xhtml.css'
+      else SiSU_Env::CSS_Default.new.xhtml
+      end
+    end
+    def xml_sax
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_xml_sax.css")
+        @md.doc_css + '_xml_sax.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_xml_sax.css")
+        @env.path.base_markup_dir_stub + '_xml_sax.css'
+      else SiSU_Env::CSS_Default.new.xml_sax
+      end
+    end
+    def xml_dom
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_xml_dom.css")
+        @md.doc_css + '_xml_dom.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_xml_dom.css")
+        @env.path.base_markup_dir_stub + '_xml_dom.css'
+      else SiSU_Env::CSS_Default.new.xml_dom
+      end
+    end
+    def xml_docbook
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_docbook.css")
+        @md.doc_css + '_xml_dom.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_docbook.css")
+        @env.path.base_markup_dir_stub + '_docbook.css'
+      else SiSU_Env::CSS_Default.new.xml_docbook
+      end
+    end
+    def homepage
+      if @md.doc_css \
+      and FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@md.doc_css}_homepage.css")
+        @md.doc_css + '_homepage.css'
+      elsif FileTest.file?("#{@env.path.output}/#{@env.path.style}/#{@env.path.base_markup_dir_stub}_homepage.css")
+        @env.path.base_markup_dir_stub + '_homepage.css'
+      else SiSU_Env::CSS_Default.new.homepage
+      end
+    end
+  end
+  class CSS_Stylesheet
+    def initialize(md)
+      @md=md
+      @css=SiSU_Env::CSS_Select.new(@md)
+      @env=SiSU_Env::InfoEnv.new('',@md)
+      @file=SiSU_Env::FileOp.new(@md)
+    end
+    def html
+      stylesheet=
+        @file.path_rel_links.html_scroll_css \
+        + @env.path.style + '/' \
+        + @css.html
+      %{   }
+    end
+    def html_seg
+      stylesheet=
+        @file.path_rel_links.html_seg_css \
+        + @env.path.style + '/' \
+        + @css.html
+      %{   }
+    end
+    def html_tables
+      stylesheet=
+        @file.path_rel_links.html_seg_css \
+        + @env.path.style + '/' \
+        + @css.html
+      %{   }
+    end
+    def xhtml_epub
+      %{   }
+    end
+    def epub
+      xhtml_epub
+    end
+    def xhtml
+      stylesheet=
+        @file.path_rel_links.xhtml_css \
+        + @env.path.style + '/' \
+        + @css.xhtml
+      %{}
+    end
+    def xml_sax
+      stylesheet=
+        @file.path_rel_links.xml_css \
+        + @env.path.style + '/' \
+        + @css.xml_sax
+      %{}
+    end
+    def xml_dom
+      stylesheet=
+        @file.path_rel_links.xml_css \
+        + @env.path.style + '/' \
+        + @css.xml_dom
+      %{}
+    end
+    def xml_docbook
+      stylesheet=
+        @file.path_rel_links.xml_css \
+        + @env.path.style + '/' \
+        + @css.xml_docbook
+      %{}
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_date.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_date.rb"
+# <>
+module SiSU_Info_Date
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class InfoDate
+    begin
+      require 'date'
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('date NOT FOUND (LoadError)')
+    end
+    attr_accessor :dt,:t
+    def initialize
+      @dt,@t=Date.today.to_s,Time.now
+    end
+    def week
+      w=@t.strftime('%W')
+      "#{@t.year}w#{w}"
+    end
+    def month
+      "#{@t.year}#{@t.month}"
+    end
+    def year
+      @t.year
+    end
+    def weekonly
+      @t.strftime('%W')
+    end
+    def monthonly
+      @t.month
+    end
+    def year_static
+      YEAR
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_db.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_db.rb"
+# <>
+module SiSU_Info_Db
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class InfoDb < SiSU_Info_Env::InfoEnv                    # se_info_env.rb
+    @@rc=nil
+    def initialize
+      @@pwd=@pwd=SiSU_Utils::Path.new.base_markup
+      @env=SiSU_Env::InfoEnv.new
+      pt=Pathname.new(@pwd)
+      r=Px[:lng_lst_rgx]
+      u=/.+?\/([^\/]+)(?:\/(?:#{r})$|$)/
+      @pwd_stub=pt.realpath.to_s[u,1]
+      @rc=@@rc ||=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @defaults=SiSU_Env::InfoEnv.new.defaults
+    end
+    def share_source?
+      ((defined? @rc['db']['share_source']) \
+      && @rc['db']['share_source']==true) \
+      ? @rc['db']['share_source']
+      : false
+    end
+    def engine
+      def default
+        ((defined? @rc['db']['engine']['default']) \
+        && @rc['db']['engine']['default']=~/postgresql|sqlite/) \
+        ? @rc['db']['engine']['default']
+        : 'sqlite'
+      end
+      self
+    end
+    def psql
+      def user(opt=nil)
+        if opt \
+        and opt.selections.str =~/--db-user[=-]["']?(\S+)["']+/
+          $1
+        elsif opt \
+        and opt.selections.str =~/--webserv[=-]webrick/
+          @env.user
+        else
+          ((defined? @rc['db']['postgresql']['user']) \
+          && @rc['db']['postgresql']['user']=~/\S+/) \
+          ? @rc['db']['postgresql']['user']
+          : @env.user
+        end
+      end
+      def db #db_name
+        "#{Db[:name_prefix]}#{@pwd_stub}"
+      end
+      def port #PGPORT
+        ((defined? @rc['db']['postgresql']['port']) \
+        && ( @rc['db']['postgresql']['port'] =~/\d+/ \
+        || @rc['db']['postgresql']['port'].is_a?(Fixnum))) \
+        ? @rc['db']['postgresql']['port']
+        : (@defaults[:postgresql_port])
+      end
+      def password
+        ((defined? @rc['db']['postgresql']['password']) \
+        && @rc['db']['postgresql']['password']=~/\S+/) \
+        ? @rc['db']['postgresql']['password']
+        : ''
+      end
+      def host
+        ((defined? @rc['db']['postgresql']['host']) \
+        && @rc['db']['postgresql']['host']=~/(?:\S{1,3}\.){3}\S{1,3}|\S+?\.\S+/) \
+        ? @rc['db']['postgresql']['host']
+        : ''
+      end
+      def dbi
+        PG::Connection.open(:dbname =>  psql.db)
+      end
+      def dbi_
+        (psql.host =~/(?:\S{1,3}\.){3}\S{1,3}|\S+?\.\S+/) \
+        ? "DBI:Pg:database=#{psql.db};host=#{psql.host};port=#{psql.port}"
+        : "DBI:Pg:database=#{psql.db};port=#{psql.port}"
+      end
+      def conn_dbi
+        DBI.connect(psql.dbi,psql.user,psql.db)
+      end
+      def conn_pg
+        begin
+          require 'pg'
+        rescue LoadError
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+            error('pg NOT FOUND (LoadError)')
+        end
+        PG::Connection.new(dbname: psql.db, port: psql.port)
+      end
+     self
+    end
+    def sqlite
+      def db
+        "#{@env.path.webserv}/#{@pwd_stub}/sisu_sqlite.db"
+      end
+      def db_discrete(md)
+        # "#{@env.path.webserv}/#{@pwd_stub}/sisu_sqlite.db"
+      end
+      def dbi
+        "DBI:SQLite3:#{sqlite.db}" #sqlite3 ?
+      end
+      def sqlite3
+        sqlite.db #sqlite3 ?
+      end
+      def conn_dbi
+        DBI.connect(sqlite.dbi)
+      end
+      def conn_sqlite3
+        SQLite3::Database.new(sqlite.sqlite3)
+      end
+      self
+    end
+  end
+end
+module SiSU_Db_Op
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class DbOp < SiSU_Info_Db::InfoDb
+    def initialize(md)
+      begin
+        @md=md
+      rescue
+        SiSU_Screen::Ansi.new(md.opt.selections.str,$!,$@).rescue do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def sqlite_discrete
+      def db
+        @md.file.output_path.sqlite_discrete.dir \
+        + '/' \
+        + @md.file.base_filename.sqlite_discrete
+      end
+      def dbi
+        "DBI:SQLite3:#{sqlite_discrete.db}"
+      end
+      def sqlite3
+        sqlite_discrete.db
+      end
+      def conn_dbi
+        DBI.connect(sqlite_discrete.dbi)
+      end
+      def conn_sqlite3
+        begin
+          $sqlite3=:yes
+          require 'sqlite3'
+          SQLite3::Database.new(sqlite_discrete.sqlite3)
+        rescue LoadError
+          $sqlite3=:no
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+            error('sqlite3 NOT FOUND (LoadError)')
+        end
+      end
+      self
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_envcall.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_envcall.rb"
+# <>
+module SiSU_Env_Call
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  class EnvCall
+    @@rc,@@fns,@@fnn,@@fnb,@@fnt,@@flv,@@fnz=nil,nil,nil,nil,nil,nil,nil
+    @@ad={}
+    attr_accessor :rc,:fnn,:fnb,:fnt,:fnv,:fnz,:ad
+    def initialize(fns='')
+      @fns=fns
+      @sys=SiSU_Info_Sys::InfoSystem.instance
+      get_init=SiSU_Env::GetInit.new
+      @rc=get_init.sisu_yaml.rc
+      @ad=get_init.ads
+      if @fns \
+      and @fns != '' \
+      and @fns !=@@fns
+        @@fns,@@fnn,@@fnb,@@fnt,@@flv,@@fnz=@fns,nil,nil,nil,nil,nil
+      end
+      if @fns \
+      and @fns != '' #watch
+        m=/((.+?)(?:\~\w\w(?:_\w\w)?)?)\.((?:-|ssm\.)?sst|ssm|ssi)$/
+        @@fnn ||=@fns[m,1]
+        @@fnb ||=@fns[m,2]
+        @@fnt ||=@fns[m,3]
+        @@flv ||=document_language_versions_found[:f]
+        unless @@fns =~/\S+?\.txz/
+          @@fnz ||=if @@fns =~/(?:\~\S{2,3})?\.(?:ssm\.sst|ssm)$/; @@fnb + '.ssm.txz'
+          elsif @@fnb; @@fnb + '.sst.txz'
+          else '' # e.g. termsheet
+          end
+        end
+      end
+      @fnn,@fnb,@fnt,@flv,@fnz=@@fnn,@@fnb,@@fnt,@@flv,@@fnz
+    end
+    def default_language?
+      if @rc \
+      && defined? @rc['language_default']
+        if (@rc['language_default'].is_a?(String)) \
+        && (@rc['language_default'] =~/#{Px[:lng_lst_rgx]}/)
+          @rc['language_default']
+        else 'en'
+        end
+      else 'en'
+      end
+    end
+    def mono_multi_lingual?
+      if @rc \
+      && defined? @rc['output_dir_structure_by']
+        if @rc['output_dir_structure_by'] \
+        =~/dump/
+          :mono
+        elsif @rc['output_dir_structure_by'] \
+        =~/language|redirect/
+          :multi
+        elsif @rc['output_dir_structure_by'] \
+        =~/monolingual|filetype_mono|filenaneme_mono/
+          :mono
+        else :multi
+        end
+      else :multi
+      end
+    end
+    def output_dir_structure
+      def by?
+        output_structure=:filename #set default output structure
+        if @rc \
+        && defined? @rc['output_dir_structure_by']
+          output_structure=if (@rc['output_dir_structure_by'] =~/dump/) \
+          or ((defined? @rc['output_structure']['dump']) \
+          && @rc['output_structure']['dump'] ==true)
+            :dump
+          elsif (@rc['output_dir_structure_by'] =~/redirect/) \
+          or ((defined? @rc['output_structure']['redirect']) \
+          && @rc['output_structure']['redirect'] ==true)
+            :redirect
+          elsif (@rc['output_dir_structure_by'] =~/language/) \
+          or ((defined? @rc['output_structure']['by_language']) \
+          && @rc['output_structure']['by_language'] ==true)
+            :language
+          elsif (@rc['output_dir_structure_by'] =~/filetype/) \
+          or ((defined? @rc['output_structure']['by_filetype']) \
+          && @rc['output_structure']['by_filetype'] ==true)
+            :filetype
+          elsif (@rc['output_dir_structure_by'] =~/filename/) \
+          or ((defined? @rc['output_structure']['by_filename']) \
+          && @rc['output_structure']['by_filename'] ==true)
+            :filename
+          else #set default
+            :language
+          end
+        else #set default
+          :language
+        end
+      end
+      def dump?
+        ((by?) ==:dump) \
+        ? true
+        : false
+      end
+      def redirect?
+        ((by?) ==:redirect) \
+        ? true
+        : false
+      end
+      def by_language_code?
+        ((by?) ==:language) \
+        ? true
+        : false
+      end
+      def by_filetype?
+        ((by?) ==:filetype) \
+        ? true
+        : false
+      end
+      def by_filename?
+        ((by?) ==:filename) \
+        ? true
+        : false
+      end
+      def multilingual?
+        by_language_code?
+      end
+      self
+    end
+    def document_language_versions_found #REVISIT
+      @fn={}
+      filename=(@fns =~/\.ssm\.sst$/) \
+      ? @fns.gsub(/\.ssm\.sst$/,'.ssm')
+      : @fns
+      if filename.is_a?(String) \
+      and not filename.empty?
+        if output_dir_structure.by_language_code?
+          m=/((.+?)(?:\~\w{2,3})?)\.(sst|ssm)$/
+          @fn[:b],@fn[:m],@fn[:t]=filename[m,1],filename[m,2],filename[m,3]
+        else m=/(.+?)\.(sst|ssm)$/
+          @fn[:b]=@fn[:m]=filename[m,1]
+          @fn[:t]=filename[m,2]
+        end
+      end
+      lng_base=SiSU_Env::InfoEnv.new.language_default_set
+      lang=SiSU_Env::StandardiseLanguage.new
+      langs=lang.codes
+      x=[]
+      if FileTest.file?("#{@fn[:m]}.#{@fn[:t]}")
+        n=@fn[:m].gsub(/^.+?\//,'')
+        n =n + '.' + @fn[:t]
+        x << { f: "#{@fn[:m]}.#{@fn[:t]}", l: lng_base, n: n }
+      end
+      langs.each do |l|
+        lng=SiSU_Env::StandardiseLanguage.new(l)
+        if FileTest.file?("#{@fn[:m]}~#{lng.code}.#{@fn[:t]}")
+          x << { f: "#{@fn[:m]}~#{lng.code}.#{@fn[:t]}", l: lng.code }
+        elsif FileTest.file?("#{@fn[:m]}~#{lng.name}.#{@fn[:t]}")
+          x << { f: "#{@fn[:m]}~#{lng.name}.#{@fn[:t]}", l: lng.code }
+        end
+        if FileTest.file?("#{lng.code}/#{@fn[:m]}~#{lng.code}.#{@fn[:t]}")
+          if FileTest.file?("#{lng.code}/#{@fn[:m]}~#{lng.code}.#{@fn[:t]}")
+            x << { f: "#{lng.code}/#{@fn[:m]}~#{lng.code}.#{@fn[:t]}", l: lng.code }
+          elsif FileTest.file?("#{lng.code}/#{@fn[:m]}~#{lng.name}.#{@fn[:t]}")
+            x << { f: "#{lng.code}/#{@fn[:m]}~#{lng.name}.#{@fn[:t]}", l: lng.code }
+          end
+        end
+        if FileTest.file?("#{lng.code}/#{@fn[:m]}.#{@fn[:t]}")
+          if FileTest.file?("#{lng.code}/#{@fn[:m]}.#{@fn[:t]}")
+            x << { f: "#{lng.code}/#{@fn[:m]}.#{@fn[:t]}", l: lng.code }
+          elsif FileTest.file?("#{lng.code}/#{@fn[:m]}.#{@fn[:t]}")
+            x << { f: "#{lng.code}/#{@fn[:m]}.#{@fn[:t]}", l: lng.code }
+          end
+        end
+      end
+      @fn[:f]=x
+      @fn
+    end
+    def published_manifests?(output_base)
+      @fn={}
+      @m=[]
+      unless (@fns.nil? \
+      or @fns.empty?)
+        if output_dir_structure.by_language_code?
+          m=/((.+?)(?:\~\w{2,3})?)\.((?:-|ssm\.)?sst$)/
+          @fn[:b],@fn[:m],@fn[:t]=@fns[m,1],@fns[m,2],@fns[m,3]
+        else m=/(.+?)\.((?:-|ssm\.)?sst$)/
+          @fn[:b]=@fn[:m]=@fns[m,1]
+          @fn[:t]=@fns[m,2]
+        end
+      end
+      lang=SiSU_Env::StandardiseLanguage.new
+      langs=lang.codes
+      x=[]
+      if FileTest.file?("#{@fn[:m]}.#{@fn[:t]}"); x << "#{@fn[:m]}.#{@fn[:t]}"
+      end
+      dir=SiSU_Env::InfoEnv.new(@fns)
+      @m << { m: 'sisu_manifest.html', l: 'English' } #fix later, default language
+      langs.each do |l|
+        lng=SiSU_Env::StandardiseLanguage.new(l)
+        fns_c="#{@fn[:m]}~#{lng.code}.#{@fn[:t]}"
+        fns_l="#{@fn[:m]}~#{lng.name}.#{@fn[:t]}"
+        if FileTest.file?(fns_c)
+          fn_set_lang=SiSU_Env::StandardiseLanguage.new.
+            file_to_language(fns_c) #reconsider file_to_language
+          lng=fn_set_lang[:n]
+          fn=SiSU_Env::EnvCall.new(fns_c).lang(fn_set_lang[:c])
+          @m << { m: fn[:manifest], l: lng }
+        elsif FileTest.file?(fns_l)
+          fn_set_lang=SiSU_Env::StandardiseLanguage.new.
+            file_to_language(fns_l) #reconsider file_to_language
+          @fnl=dir.i18n.lang_filename(fn_set_lang[:c])
+          fn=SiSU_Env::EnvCall.new(fns_l).lang(fn_set_lang[:c])
+          @m << { m: fn[:manifest], l: lng }
+        end
+      end
+      @m=@m.uniq
+    end
+    def filename(code,name,suffix)
+      "#{name}#{suffix}"
+    end
+    def lang(code)
+      {
+        html:            filename(code,'','.html'),
+        book_index:      filename(code,'book_index','.html'),
+        concordance:     filename(code,'concordance','.html'),
+        sax:             filename(code,'sax','.xml'),
+        dom:             filename(code,'dom','.xml'),
+        docbook:         filename(code,'docbook','.xml'),
+        xhtml:           filename(code,'scroll','.xhtml'),
+        pdf_l:           filename(code,'','.pdf'),
+        pdf_p:           filename(code,'','.pdf'),
+        pdf_l_a4:        filename(code,"a4",'.pdf'),
+        pdf_p_a4:        filename(code,"a4",'.pdf'),
+        pdf_l_a5:        filename(code,"a5",'.pdf'),
+        pdf_p_a5:        filename(code,"a5",'.pdf'),
+        pdf_l_b5:        filename(code,"b5",'.pdf'),
+        pdf_p_b5:        filename(code,"b5",'.pdf'),
+        pdf_l_letter:    filename(code,"letter",'.pdf'),
+        pdf_p_letter:    filename(code,"letter",'.pdf'),
+        pdf_l_legal:     filename(code,"legal",'.pdf'),
+        pdf_p_legal:     filename(code,"legal",'.pdf'),
+        toc:             filename(code,'toc','.html'),
+        doc:             filename(code,fnb,'.html'),
+        index:           filename(code,'index','.html'),
+        po:              filename(code,@fns,'.po'),
+        pot:             filename(code,@fns,'.pot'),
+        odf:             filename(code,'','.odt'),
+        epub:            filename(code,'','.epub'),
+        plain:           filename(code,'','.txt'),
+        qrcode:          filename(code,'','.jpg'),
+        manpage:         filename(code,'','.1'),          #fix, section number
+        wiki:            filename(code,'wiki','.txt'),
+        digest:          filename(code,'digest','.txt'),
+        metadata:        filename(code,'metadata','.html'), #chk
+        manifest:        filename(code,'manifest','.html'),
+        oai_pmh:         filename(code,'oai_pmh','.xml'),
+        sitemap:         filename(code,'sitemap','.xml'),
+        sitemap_touch:   filename(code,"sitemap_#{fnb}",'.xml'),
+        sxs:             filename(code,fnb,'.sxs.xml'),
+        sxd:             filename(code,fnb,'.sxd.xml'),
+        sxn:             filename(code,fnb,'.sxn.xml'),
+        sisupod:         filename(nil,@fnz,''),
+        book_idx_html:   filename(code,'book_index','.html'),
+        book_idx_epub:   filename(code,'book_index','.xhtml'),
+        epub_concord:    filename(code,'concordance','.xhtml'),
+      }
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_filemap.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_filemap.rb"
+# <>
+module SiSU_File_Map
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class FileMap < SiSU_Info_Env::InfoEnv                   # se_info_env.rb
+    attr_accessor :local_sisu_source
+    def initialize(opt='') #watch / REVIEW
+      super()
+      @opt=opt #,opt.fns,opt.selections.str
+      @env=(@opt.fns && !(@opt.fns.empty?) \
+      ? (SiSU_Env::InfoEnv.new(@opt.fns))
+      : (SiSU_Env::InfoEnv.new('dummy.sst')))
+      ft=[]
+      if @opt.act[:ao][:set]==:on
+        @md=SiSU_Param::Parameters.new(@opt).get
+        if @md \
+        and defined? @md.fn \
+        and @md.fn        # used for by_language_code?
+          if @md.opt.act[:html][:set]==:on                 #% --html, -h -H
+            ft << @md.fn[:html]
+          end
+          if @md.opt.act[:concordance][:set]==:on          #% --concordance, -w
+            ft << @md.fn[:concordance]
+          end
+          if @md.opt.act[:manifest][:set]==:on             #% --manifest, -y
+            ft << @md.fn[:manifest]
+          end
+          if @md.opt.act[:txt][:set]==:on                  #% --txt, -t -a
+            ft << @md.fn[:plain]
+          end
+          if @md.opt.act[:txt_textile][:set]==:on          #% --textile
+            ft << @md.fn[:txt_textile]
+          end
+          if @md.opt.act[:txt_asciidoc][:set]==:on         #% --asciidoc
+            ft << @md.fn[:txt_asciidoc]
+          end
+          if @md.opt.act[:txt_markdown][:set]==:on         #% --markdown
+            ft << @md.fn[:txt_markdown]
+          end
+          if @md.opt.act[:txt_rst][:set]==:on              #% --rst, --rest
+            ft << @md.fn[:txt_rst]
+          end
+          if @md.opt.act[:txt_orgmode][:set]==:on          #% --orgmode
+            ft << @md.fn[:txt_orgmode]
+          end
+          if @md.opt.act[:xhtml][:set]==:on                #% --xhtml, -b xhtml
+            ft << @md.fn[:xhtml]
+          end
+          if @md.opt.act[:epub][:set]==:on                 #% --epub, -e
+            ft << @md.fn[:epub]
+          end
+          if @md.opt.act[:manpage][:set]==:on              #% --manpage, -i
+            ft << @md.fn[:manpage]
+          end
+          if @md.opt.act[:hash_digests][:set]==:on         #% --hash-digests, -N digest tree
+            ft << @md.fn[:digest]
+          end
+          if @md.opt.act[:odt][:set]==:on                  #% --odt, -o opendocument
+            ft << @md.fn[:odf]
+          end
+          if @md.opt.act[:pdf][:set]==:on                  #% --pdf-l --pdf, -p latex/ texpdf
+            ft << @md.fn[:pdf_l] << @md.fn[:pdf_p]
+          end
+          if @md.opt.act[:share_source][:set]==:on
+            ft << @md.fns
+          end
+          if @md.opt.act[:sisupod][:set]==:on              #% --sisupod, -S make sisupod
+            ft << @md.fn[:sisupod]
+          end
+          if @md.opt.act[:xml_sax][:set]==:on              #% --xml-sax, -x xml sax type
+            ft << @md.fn[:sax]
+          end
+          if @md.opt.act[:xml_dom][:set]==:on              #% --xml-dom, -X xml dom type
+            ft << @md.fn[:dom]
+          end
+          if @md.opt.act[:xml_docbook_book][:set]==:on     #% --xml-docbook-book
+            ft << @md.fn[:xml_docbook_book]
+          end
+          if @md.opt.act[:xml_fictionbook][:set]==:on      #% --xml-fictionbook
+            ft << @md.fn[:xml_fictionbook]
+          end
+          if @md.opt.act[:xml_scaffold_structure_sisu][:set]==:on          #% --xml-scaffold --xml-scaffold-sisu
+            ft << @md.fn[:xml_scaffold_structure_sisu]
+          end
+          if @md.opt.act[:xml_scaffold_structure_collapse][:set]==:on      #% --xml-scaffold-collapse
+            ft << @md.fn[:xml_scaffold_structure_collapse]
+          end
+          @fnb=@md.fnb
+        else   # still needed where/when dp document param is not parsed
+          if @opt.act[:html][:set]==:on                    #% --html, -h -H
+            ft << '.html' << '.html.??'
+          end
+          if @opt.act[:concordance][:set]==:on             #% --concordance, -w
+            ft << 'concordance.html' << '??.concordance.html' << 'concordance.??.html'
+          end
+          if @opt.act[:manifest][:set]==:on                #% --manifest, -y
+            ft << 'sisu_manifest.html' << '??.sisu_manifest.html' << 'sisu_manifest.??.html'
+          end
+          if @opt.act[:txt][:set]==:on                     #% --txt, -t -a
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:txt_textile][:set]==:on             #% --textile
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:txt_asciidoc][:set]==:on            #% --asciidoc
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:txt_markdown][:set]==:on            #% --markdown
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:txt_rst][:set]==:on                 #% --rst, --rest
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:txt_orgmode][:set]==:on             #% --orgmode
+            ft << 'plain.txt' << '??.plain.txt' << 'plain.??.txt'
+          end
+          if @opt.act[:xhtml][:set]==:on                   #% --xhtml, -b xhtml
+            ft << 'scroll.xhtml' << '??.scroll.xhtml' << 'scroll.??.xhtml'
+          end
+          if @opt.act[:epub][:set]==:on                    #% --epub, -e
+            ft  << @fnb << '.epub'
+          end
+          if @opt.act[:manpage][:set]==:on                 #% --manpage, -i
+            ft << '.1' << '??.man.1' << 'man.??.1'
+          end
+          if @opt.act[:hash_digests][:set]==:on            #% --hash-digests, -N digest tree
+            ft << 'digest.txt' << '??.digest.txt' << 'digest.??.txt'
+          end
+          if @opt.act[:odt][:set]==:on                     #% --odt, -o opendocument
+            ft << 'opendocument.odt' << '??.opendocument.odt' << 'opendocument.??.odt'
+          end
+          if @opt.act[:pdf][:set]==:on                     #% --pdf-l --pdf, -p latex/ texpdf
+            ft << 'landscape.pdf' << 'portrait.pdf' << '.pdf'
+          end
+          if @opt.act[:share_source][:set]==:on
+            ft << '.sst' << '.ssi' << '.ssm'
+          end
+          if @opt.act[:sisupod][:set]==:on                 #% --sisupod, -S make sisupod
+            ft << '.zip'
+          end
+          if @opt.act[:xml_sax][:set]==:on                 #% --xml-sax, -x xml sax type
+            ft << 'sax.xml' << '??.sax.xml' << 'sax.??.xml'
+          end
+          if @opt.act[:xml_dom][:set]==:on                 #% --xml-dom, -X xml dom type
+            ft << 'dom.xml' << '??.dom.xml' << 'dom.??.xml'
+          end
+          if @opt.act[:xml_docbook_book][:set]==:on        #% --xml-docbook-book
+            ft << 'docbook.xml' << '??.docbook.xml' << 'docbook.??.xml'
+          end
+          if @opt.act[:xml_fictionbook][:set]==:on         #% --xml-fictionbook
+            ft << 'fictionbook.xml' << '??.fictionbook.xml' << 'fictionbook.??.xml'
+          end
+          if @opt.act[:xml_scaffold_structure_sisu][:set]==:on          #% --xml-scaffold --xml-scaffold-sisu
+            ft << 'scaffold.xml' << '??.scaffold.xml' << 'scaffold.??.xml'
+          end
+          if @opt.act[:xml_scaffold_structure_collapse][:set]==:on      #% --xml-scaffold-collapse
+            ft << 'scaffold.xml' << '??.scaffold.xml' << 'scaffold.??.xml'
+          end
+        end
+        ft=ft.uniq
+        filetypes=ft.join(',')
+        @filetypes=if filetypes !~/..+/ then ''   # -r called alone, copy all
+        elsif @opt.selections.str =~/u/            then ''   # -u added, copy all, (used to create remote directory tree see output path), not the usual function of -u
+        elsif filetypes =~/\S+?,\S+/    then '*{' + filetypes + '}' # more than one relevant file type
+        else                                 '*' + filetypes # one relevant file type
+        end
+        @source_path=(@fnb && !(@fnb.empty?) \
+        ? "#{@env.path.output}/#{@fnb}"
+        : @env.path.output)
+        @source_path_epub=(@fnb && !(@fnb.empty?) \
+        ? "#{@env.path.output}/epub"
+        : @env.path.output_epub)
+        @source_path_src=(@fnb && !(@fnb.empty?) \
+        ? "#{@env.path.output}/src"
+        : @env.path.output_src)
+        @source_path_pod=(@fnb && !(@fnb.empty?) \
+        ? "#{@env.path.output}/pod"
+        : @env.path.output_pod)
+        @source_path_harvest=(@fnb && !(@fnb.empty?) \
+        ? "#{@env.path.output}/manifest"
+        : @env.path.output_harvest)
+        @local_sisu_source=(@filetypes =~/\S/) \
+        ? "#{@source_path}/#{@filetypes}"
+        : @source_path
+      end
+      if @opt.act[:rsync][:set]==:on
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_file_op.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_file_op.rb"
+# <>
+module SiSU_Info_File
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  begin
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('fileutils NOT FOUND (LoadError)')
+  end
+  class InfoFile < SiSU_Info_Env::InfoEnv                  # se_info_env.rb
+    #todo unify with FileOp
+    def initialize(fns)
+      begin
+        super(fns)
+        @fns=fns
+        @env=SiSU_Env::InfoEnv.new(@fns)
+        m=/((.+?)(?:\~\w\w(?:_\w\w)?)?)\.((?:-|ssm\.)?sst|ssm)$/
+        @fnn,@fnb,@fnt=@fns[m,1],@fns[m,2],@fns[m,3]
+      rescue
+        SiSU_Screen::Ansi.new('',$!,$@).rescue do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def basefilename #Remove if possible
+      m=/(.+?)\.(?:(?:-|ssm\.)?sst|ssm)$/m
+      @fns[m,1]
+    end
+    def make_file(path,filename)
+      (File.writable?("#{path}/.")) \
+      ? File.new("#{path}/#{filename}",'w+')
+      : (SiSU_Screen::Ansi.new(
+          '',
+          "*WARN* is the file or directory writable?, could not create #{filename}"
+        ).warn)
+    end
+    def touch_file(path,filename)
+      if File.writable?("#{path}/.");
+        FileUtils::touch("#{path}/#{filename}")
+      else
+        SiSU_Screen::Ansi.new(
+          '',
+          "*WARN* is the file or directory writable?, could not create #{filename}"
+        ).warn
+      end
+    end
+    def make_path(path)
+      FileUtils::mkdir_p(path) unless FileTest.directory?(path)
+    end
+    def marshal
+      def ao_content
+        @env.processing_path.ao + '/' \
+          + @fns + '.content.rbm'
+      end
+      def ao_idx_sst_rel_html_seg
+        @env.processing_path.ao + '/' \
+          + @fns + '.idx_sst.rbm'
+      end
+      def ao_idx_sst_rel #used by tex & odf
+        @env.processing_path.ao + '/' \
+          + @fns + '.idx_raw.rbm'
+      end
+      def ao_idx_html
+        @env.processing_path.ao + '/' \
+          + @fns + '.idx_html.rbm'
+      end
+      def ao_idx_xhtml
+        @env.processing_path.ao + '/' \
+          + @fns + '.idx_xhtml.rbm'
+      end
+      def ao_metadata
+        @env.processing_path.ao + '/' \
+          + @fns + '.metadata.rbm'
+      end
+      def ao_map_nametags
+        @env.processing_path.ao + '/' \
+          + @fns + '.map_name_tags.rbm'
+      end
+      def ao_map_ocn_htmlseg
+        @env.processing_path.ao + '/' \
+          + @fns + '.map_ocn_htmlseg.rbm'
+      end
+      def html_tune
+        @env.processing_path.tune + '/' \
+          + @fns + '.marshal_tune'
+      end
+      def xhtml_tune
+        @env.processing_path.tune + '/' \
+          + @fns + '.marshal_tune'
+      end
+      self
+    end
+    def write_file_processing
+      def html_tune
+        File.new("#{@env.processing_path.tune}/#{@fns}.tune",'w+')
+      end
+      self
+    end
+    def mkdir #check moved from FileOp, existing mkdir
+      def processing
+        def ao
+          FileUtils::mkdir_p(@env.processing_path.ao) \
+            unless FileTest.directory?(@env.processing_path.ao)
+        end
+        def tune
+          FileUtils::mkdir_p(@env.processing_path.tune) \
+            unless FileTest.directory?(@env.processing_path.tune)
+        end
+        self
+      end
+    end
+  end
+end
+module SiSU_File_Op
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  begin
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('fileutils NOT FOUND (LoadError)')
+  end
+  class FileOp < SiSU_Info_File::InfoFile
+    #todo unify with CreateFile
+    def initialize(md,fno='')
+      begin
+        @md,@fno=md,fno
+        @env=SiSU_Env::InfoEnv.new(@md.fns)
+      rescue
+        SiSU_Screen::Ansi.new(md.opt.selections.str,$!,$@).rescue do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def output_dir_structure
+      SiSU_Env::ProcessingSettings.new(@md).output_dir_structure
+    end
+    def mkdir_initialize                # not used but consider using
+      FileUtils::mkdir_p(output_path.base.dir) \
+        unless FileTest.directory?(output_path.base.dir)
+      FileUtils::mkdir_p("#{output_path.base.dir}/#{@md.fnb}") \
+        unless FileTest.directory?("#{output_path.base.dir}/#{@md.fnb}")
+      FileUtils::mkdir_p("#{output_path.base.dir}/#{@env.path.style}") \
+        unless FileTest.directory?("#{output_path.base.dir}/#{@env.path.style}")
+      FileUtils::mkdir_p(@env.processing_path.ao) \
+        unless FileTest.directory?(@env.processing_path.ao)
+      FileUtils::mkdir_p(@env.processing_path.tune) \
+        unless FileTest.directory?(@env.processing_path.tune)
+    end
+    def path_rel_links
+      def html_scroll_2
+        if output_dir_structure.by_language_code?
+          '../../'
+        elsif output_dir_structure.by_filetype?
+          '../'
+        else
+          '../'
+        end
+      end
+      def html_seg_2
+        if output_dir_structure.by_language_code?
+          '../../../'
+        elsif output_dir_structure.by_filetype?
+          '../../'
+        else
+          '../'
+        end
+      end
+      def html_scroll_1
+        if output_dir_structure.by_language_code?
+          '../'
+        elsif output_dir_structure.by_filetype?
+          '../'
+        else
+          './'
+        end
+      end
+      def html_seg_1
+        if output_dir_structure.by_language_code?
+          '../../'
+        elsif output_dir_structure.by_filetype?
+          '../../'
+        else
+          './'
+        end
+      end
+      def default_output_css
+        if (@md.opt.opt_act[:dump][:bool] \
+        &&  @md.opt.opt_act[:dump][:inst]) \
+        || (@md.opt.opt_act[:redirect][:bool] \
+        &&  @md.opt.opt_act[:redirect][:inst])
+          './'
+        elsif output_dir_structure.by_language_code?
+          '../../'
+        elsif output_dir_structure.by_filetype?
+          '../'
+        else
+          '../'
+        end
+      end
+      def html_scroll_css
+        default_output_css
+      end
+      def xhtml_css
+        default_output_css
+      end
+      def xml_css
+        default_output_css
+      end
+      def html_seg_css
+        if output_dir_structure.by_language_code?
+          '../../../'
+        elsif output_dir_structure.by_filetype?
+          '../../'
+        else
+          '../'
+        end
+      end
+      def manifest_css
+        if output_dir_structure.by_language_code?
+          '../../_sisu/css'
+        elsif output_dir_structure.by_filetype?
+          ''
+        else
+          '../'
+        end
+      end
+      self
+    end
+    def mkdir
+      def output
+        def base
+          FileUtils::mkdir_p(output_path.base.dir) \
+            unless FileTest.directory?(output_path.base.dir)
+        end
+        def css
+          FileUtils::mkdir_p("#{output_path.base.dir}/#{@env.path.style}") \
+            unless FileTest.directory?("#{output_path.base.dir}/#{@env.path.style}")
+        end
+        def epub
+          path=output_path.epub.dir
+          make_path(path)
+        end
+        self
+      end
+      self
+    end
+    def mkfile #consider using more
+      path="#{output_path.base.dir}/#{@md.fnb}"
+      make_path(path)
+      filename=@fno
+      make_file(path,filename)
+    end
+    def mkfile_pwd
+      path=Dir.pwd
+      filename=@fno
+      make_file(path,filename)
+    end
+    def write_file
+      def txt
+        path=output_path.txt.dir
+        make_path(path)
+        fn=base_filename.txt
+        make_file(path,fn)
+      end
+      def textile
+        path=output_path.textile.dir
+        make_path(path)
+        fn=base_filename.textile
+        make_file(path,fn)
+      end
+      def asciidoc
+        path=output_path.asciidoc.dir
+        make_path(path)
+        fn=base_filename.asciidoc
+        make_file(path,fn)
+      end
+      def markdown
+        path=output_path.markdown.dir
+        make_path(path)
+        fn=base_filename.markdown
+        make_file(path,fn)
+      end
+      def rst
+        path=output_path.rst.dir
+        make_path(path)
+        fn=base_filename.rst
+        make_file(path,fn)
+      end
+      def orgmode
+        path=output_path.orgmode.dir
+        make_path(path)
+        fn=base_filename.orgmode
+        make_file(path,fn)
+      end
+      def html_scroll
+        pth=output_path.html.dir
+        make_path(pth)
+        p_fn=place_file.html_scroll.dir
+        File.new(p_fn,'w+')
+      end
+      def html_seg_index
+        pth=((output_dir_structure.by_filename?) \
+        || (output_dir_structure.dump?)) \
+        ? "#{output_path.html.dir}"
+        : "#{output_path.html.dir}/#{@md.fnb}"
+        make_path(pth)
+        p_fn=place_file.html_seg_index.dir
+        File.new(p_fn,'w+')
+      end
+      def html_segtoc
+        pth=((output_dir_structure.by_filename?) \
+        || (output_dir_structure.dump?) \
+        || (output_dir_structure.redirect?)) \
+        ? "#{output_path.html.dir}"
+        : "#{output_path.html.dir}/#{@md.fnb}"
+        make_path(pth)
+        p_fn=place_file.html_segtoc.dir
+        File.new(p_fn,'w+')
+      end
+      def xhtml
+        path=output_path.xhtml.dir
+        make_path(path)
+        fn=base_filename.xhtml
+        make_file(path,fn)
+      end
+      def xml_sax
+        path=output_path.xml.dir
+        make_path(path)
+        fn=base_filename.xml_sax
+        make_file(path,fn)
+      end
+      def xml_dom
+        path=output_path.xml.dir
+        make_path(path)
+        fn=base_filename.xml_dom
+        make_file(path,fn)
+      end
+      def xml_docbook_book
+        path=output_path.xml_docbook_book.dir
+        make_path(path)
+        fn=base_filename.xml_docbook_book
+        make_file(path,fn)
+      end
+      def xml_fictionbook
+        path=output_path.xml_fictionbook.dir
+        make_path(path)
+        fn=base_filename.xml_fictionbook
+        make_file(path,fn)
+      end
+      def xml_scaffold_structure_sisu
+        path=output_path.xml_scaffold_structure_sisu.dir
+        make_path(path)
+        fn=base_filename.xml_scaffold_structure_sisu
+        make_file(path,fn)
+      end
+      def xml_scaffold_structure_collapse
+        path=output_path.xml_scaffold_structure_collapse.dir
+        make_path(path)
+        fn=base_filename.xml_scaffold_structure_collapse
+        make_file(path,fn)
+      end
+      def json
+        path=output_path.json.dir
+        make_path(path)
+        fn=base_filename.json
+        make_file(path,fn)
+      end
+      def manpage
+        path=output_path.manpage.dir
+        make_path(path)
+        fn=base_filename.manpage
+        make_file(path,fn)
+      end
+      def texinfo
+        path=output_path.texinfo.dir
+        make_path(path)
+        fn=base_filename.texinfo
+        make_file(path,fn)
+      end
+      def info
+        path=output_path.texinfo.dir
+        make_path(path)
+        fn=base_filename.info
+        make_file(path,fn)
+      end
+      def hash_digest
+        path=output_path.hash_digest.dir
+        make_path(path)
+        fn=base_filename.hash_digest
+        make_file(path,fn)
+      end
+      def qrcode
+        path=output_path.qrcode.dir
+        make_path(path)
+        fn=base_filename.qrcode
+        make_file(path,fn)
+      end
+      def manifest
+        path=output_path.manifest.dir
+        make_path(path)
+        fn=base_filename.manifest
+        make_file(path,fn)
+      end
+      def manifest_txt
+        path=output_path.manifest.dir
+        make_path(path)
+        fn=base_filename.manifest_txt
+        make_file(path,fn)
+      end
+      def po4a_cfg
+        path=output_path.po4a.dir
+        make_path(path)
+        fn=base_filename.po4a_cfg
+        make_file(path,fn)
+      end
+      def pot
+        path=output_path.pot.dir
+        make_path(path)
+        fn=base_filename.pot
+        make_file(path,fn)
+      end
+      def po(lng=@md.opt.lng)
+        path=output_path.po(lng).dir
+        make_path(path)
+        fn=base_filename.po
+        make_file(path,fn)
+      end
+      def po4a_sst(lng=@md.opt.lng)
+        path=output_path.po4a_sst(lng).dir
+        make_path(path)
+        fn=base_filename.po4a_sst
+        make_file(path,fn)
+      end
+      self
+    end
+    def place_file
+      def txt
+        def dir
+          output_path.txt.dir + '/' \
+          + base_filename.txt
+        end
+        def rel
+          output_path.txt.rel + '/' \
+          + base_filename.txt
+        end
+        self
+      end
+      def textile
+        def dir
+          output_path.textile.dir + '/' \
+          + base_filename.textile
+        end
+        def rel
+          output_path.textile.rel + '/' \
+          + base_filename.textile
+        end
+        self
+      end
+      def asciidoc
+        def dir
+          output_path.asciidoc.dir + '/' \
+          + base_filename.asciidoc
+        end
+        def rel
+          output_path.asciidoc.rel + '/' \
+          + base_filename.asciidoc
+        end
+        self
+      end
+      def markdown
+        def dir
+          output_path.markdown.dir + '/' \
+          + base_filename.markdown
+        end
+        def rel
+          output_path.markdown.rel + '/' \
+          + base_filename.markdown
+        end
+        self
+      end
+      def rst
+        def dir
+          output_path.rst.dir + '/' \
+          + base_filename.rst
+        end
+        def rel
+          output_path.rst.rel + '/' \
+          + base_filename.rst
+        end
+        self
+      end
+      def orgmode
+        def dir
+          output_path.orgmode.dir + '/' \
+          + base_filename.orgmode
+        end
+        def rel
+          output_path.orgmode.rel + '/' \
+          + base_filename.orgmode
+        end
+        self
+      end
+      def html_scroll
+        def dir
+          output_path.html_scroll.dir + '/' \
+          + base_filename.html_scroll
+        end
+        def rel
+          output_path.html_scroll.rel + '/' \
+          + base_filename.html_scroll
+        end
+        self
+      end
+      def html_seg_index
+        def dir
+          output_path.html_seg.dir + '/' \
+          + base_filename.html_seg_index
+        end
+        def rel
+          output_path.html_seg.rel + '/' \
+          + base_filename.html_seg_index
+        end
+        self
+      end
+      def html_segtoc
+        def dir
+          output_path.html_seg.dir + '/' \
+          + base_filename.html_segtoc
+        end
+        def rel
+          output_path.html_seg.rel + '/' \
+          + base_filename.html_segtoc
+        end
+        self
+      end
+      def html_book_index
+        def dir
+          output_path.html_seg.dir + '/' \
+          + base_filename.html_book_index
+        end
+        def rel
+          output_path.html_seg.rel + '/' \
+          + base_filename.html_book_index
+        end
+        self
+      end
+      def html_concordance
+        def dir
+          output_path.html_seg.dir + '/' \
+          + base_filename.html_concordance
+        end
+        def rel
+          output_path.html_seg.rel + '/' \
+          + base_filename.html_concordance
+        end
+        self
+      end
+      def odt
+        def dir
+          output_path.odt.dir + '/' \
+          + base_filename.odt
+        end
+        def rel
+          output_path.odt.rel + '/' \
+          + base_filename.odt
+        end
+        self
+      end
+      def epub
+        def dir
+          output_path.epub.dir + '/' \
+          + base_filename.epub
+        end
+        def rel
+          output_path.epub.rel + '/' \
+          + base_filename.epub
+        end
+        self
+      end
+      def pdf_p
+        STDERR.puts 'ERROR not available due to multiple page format sizes'
+      end
+      def pdf_l
+        STDERR.puts 'ERROR not available due to multiple page format sizes'
+      end
+      def xhtml
+        def dir
+          output_path.xhtml.dir + '/' \
+          + base_filename.xhtml
+        end
+        def rel
+          output_path.xhtml.rel + '/' \
+          + base_filename.xhtml
+        end
+        self
+      end
+      def xml_sax
+        def dir
+          output_path.xml.dir + '/' \
+          + base_filename.xml_sax
+        end
+        def rel
+          output_path.xml.rel + '/' \
+          + base_filename.xml_sax
+        end
+        self
+      end
+      def xml_dom
+        def dir
+          output_path.xml.dir + '/' \
+          + base_filename.xml_dom
+        end
+        def rel
+          output_path.xml.rel + '/' \
+          + base_filename.xml_dom
+        end
+        self
+      end
+      def xml_docbook_book
+        def dir
+          output_path.xml_docbook.dir + '/' \
+          + base_filename.xml_docbook_book
+        end
+        def rel
+          output_path.xml_docbook.rel + '/' \
+          + base_filename.xml_docbook_book
+        end
+        self
+      end
+      def xml_fictionbook
+        def dir
+          output_path.xml_fictionbook.dir + '/' \
+          + base_filename.xml_fictionbook
+        end
+        def rel
+          output_path.xml_fictionbook.rel + '/' \
+          + base_filename.xml_fictionbook
+        end
+        self
+      end
+      def xml_scaffold_structure_sisu
+        def dir
+          output_path.xml.dir + '/' \
+          + base_filename.xml_scaffold_structure_sisu
+        end
+        def rel
+          output_path.xml.rel + '/' \
+          + base_filename.xml_scaffold_structure_sisu
+        end
+        self
+      end
+      def xml_scaffold_structure_collapse
+        def dir
+          output_path.xml.dir + '/' \
+          + base_filename.xml_scaffold_structure_collapse
+        end
+        def rel
+          output_path.xml.rel + '/' \
+          + base_filename.xml_scaffold_structure_collapse
+        end
+        self
+      end
+      def json
+        def dir
+          output_path.json.dir + '/' \
+          + base_filename.json
+        end
+        def rel
+          output_path.json.rel + '/' \
+          + base_filename.json
+        end
+        self
+      end
+      def sqlite_discrete
+        def dir
+          output_path.sqlite_discrete.dir + '/' \
+          + base_filename.sqlite_discrete
+        end
+        def rel
+          output_path.sqlite_discrete.rel + '/' \
+          + base_filename.sqlite_discrete
+        end
+        self
+      end
+      def hash_digest
+        def dir
+          output_path.hash_digest.dir + '/' \
+          + base_filename.hash_digest
+        end
+        def rel
+          output_path.hash_digest.rel + '/' \
+          + base_filename.hash_digest
+        end
+        self
+      end
+      def src
+        def dir
+          output_path.src.dir + '/' \
+            + base_filename.src
+        end
+        def rel
+          output_path.src.rel + '/' \
+          + base_filename.src
+        end
+        self
+      end
+      def sisupod
+        def dir
+          output_path.sisupod.dir + '/' \
+          + base_filename.sisupod
+        end
+        def rel
+          output_path.sisupod.rel + '/' \
+          + base_filename.sisupod
+        end
+        self
+      end
+      def po
+        def dir
+          output_path.po.dir + '/' \
+          + base_filename.po
+        end
+        def rel
+          output_path.po.rel + '/' \
+          + base_filename.po
+        end
+        self
+      end
+      def pot
+        def dir
+          output_path.pot.dir + '/' \
+          + base_filename.pot
+        end
+        def rel
+          output_path.pot.rel + '/' \
+          + base_filename.pot
+        end
+        self
+      end
+      def po_git
+        def dir
+          output_path.po_git + '/' \
+          + base_filename.po
+        end
+        def rel
+          #output_path.po_git + '/' + base_filename.po
+        end
+        self
+      end
+      def pot_git
+        def dir
+          output_path.pot_git + '/' \
+          + base_filename.pot
+        end
+        def rel
+          #output_path.pot_git + '/' + base_filename.pot
+        end
+        self
+      end
+      def manpage
+        def dir
+          output_path.manpage.dir + '/' \
+          + base_filename.manpage
+        end
+        def rel
+          output_path.manpage.rel + '/' \
+          + base_filename.manpage
+        end
+        self
+      end
+      def texinfo
+        def dir
+          output_path.texinfo.dir + '/' \
+          + base_filename.texinfo
+        end
+        def rel
+          output_path.texinfo.rel + '/' \
+          + base_filename.texinfo
+        end
+        self
+      end
+      def info
+        def dir
+          output_path.texinfo.dir + '/' \
+          + base_filename.info
+        end
+        def rel
+          output_path.texinfo.rel + '/' \
+          + base_filename.info
+        end
+        self
+      end
+      def qrcode_title
+        def dir
+          output_path.qrcode.dir + '/' \
+          + base_filename.qrcode_title
+        end
+        def rel
+          output_path.qrcode.rel + '/' \
+          + base_filename.qrcode_title
+        end
+        self
+      end
+      def qrcode_md
+        def dir
+          output_path.qrcode.dir + '/' \
+          + base_filename.qrcode_md
+        end
+        def rel
+          output_path.qrcode.rel + '/' \
+          + base_filename.qrcode_md
+        end
+        self
+      end
+      def manifest
+        def dir
+          output_path.manifest.dir + '/' \
+            + base_filename.manifest
+        end
+        def rel
+          output_path.manifest.rel + '/' \
+            + base_filename.manifest
+        end
+        self
+      end
+      self
+    end
+    def base_filename
+      def i18n(f)
+        f=default_hash.merge(f)
+        f[:lng] ||=@md.lang_code_insert
+        f[:fn] + f[:lng] + f[:ft]
+      end
+      def default_hash
+        {
+          fn: @md.fnb,
+          lng: @md.lang_code_insert,
+        }
+      end
+      def default_hash_build(fh,sfx)
+        if fh.is_a?(Hash)
+          fh[:fn] ||=@md.fnb
+          fh[:lng] ||= @md.lang_code_insert
+          fh[:ft]=sfx
+          fh
+        else
+          {
+            fn: @md.fnb,
+            lng: @md.lang_code_insert,
+            ft: sfx,
+          }
+        end
+      end
+      def lang_code?(lng)
+        (output_dir_structure.by_language_code?) \
+        ? ''
+        : (lng ||=@md.lang_code_insert)
+      end
+      def txt(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def textile(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt_textile])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def asciidoc(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt_asciidoc])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def markdown(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt_markdown])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def rst(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt_rst])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def orgmode(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt_orgmode])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'plain',
+            ft: fh[:ft],
+            lng: fh[:lng],
+           }
+         else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def html_scroll(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def html_seg_index(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: 'index',
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def html_segtoc(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fnh=if output_dir_structure.dump_or_redirect?
+          {
+            fn: fh[:fn] + '.toc',
+            ft: fh[:ft],
+          }
+        else
+          {
+            fn: 'toc',
+            ft: fh[:ft],
+            lng: lang_code?(fh[:lng]),
+          }
+        end
+        i18n(fnh)
+      end
+      def html_seg(fh)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def html_book_index(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: 'book_index',
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def html_concordance(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.dump_or_redirect?
+          {
+            fn: 'concordance',
+            ft: fh[:ft],
+          }
+        else
+          {
+            fn: 'concordance',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xhtml(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xhtml])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def epub(fh=nil)
+        fh=default_hash_build(fh,Sfx[:epub])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def odt(fh=nil)
+        fh=default_hash_build(fh,Sfx[:odt])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'opendocument',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_sax(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_sax])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_dom(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_dom])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_docbook_book(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_docbook_book])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_fictionbook(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_fictionbook])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_scaffold_structure_sisu(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_scaffold_structure_sisu])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def xml_scaffold_structure_collapse(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml_scaffold_structure_collapse])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def json(fh=nil)
+        fh=default_hash_build(fh,Sfx[:json])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'scroll',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def pdf_p(fh=nil)
+        fh=default_hash_build(fh,Sfx[:pdf])
+        fh[:lng]=lang_code?(fh[:lng])
+        if output_dir_structure.by_filename?
+          'portrait' + fh[:lng] + '.'
+        else
+          fh[:fn] + '.portrait' + fh[:lng] + '.'
+        end
+      end
+      def pdf_l(fh=nil)
+        fh=default_hash_build(fh,Sfx[:pdf])
+        fh[:lng]=lang_code?(fh[:lng])
+        if output_dir_structure.by_filename?
+          'landscape' + fh[:lng] + '.'
+        else
+          fh[:fn] + '.landscape' + fh[:lng] + '.'
+        end
+      end
+      def pdf_p_a4(fh=nil)
+        pdf_p(fh) + @md.fn[:pdf_p_a4]
+      end
+      def pdf_p_a5(fh=nil)
+        pdf_p(fh) + @md.fn[:pdf_p_a5]
+      end
+      def pdf_p_b5(fh=nil)
+        pdf_p(fh) + @md.fn[:pdf_p_b5]
+      end
+      def pdf_p_letter(fh=nil)
+        pdf_p(fh) + @md.fn[:pdf_p_letter]
+      end
+      def pdf_p_legal(fh=nil)
+        pdf_p(fh) + @md.fn[:pdf_p_legal]
+      end
+      def pdf_l_a4(fh=nil)
+        pdf_l(fh) + @md.fn[:pdf_l_a4]
+      end
+      def pdf_l_a5(fh=nil)
+        pdf_l(fh) + @md.fn[:pdf_l_a5]
+      end
+      def pdf_l_b5(fh=nil)
+        pdf_l(fh) + @md.fn[:pdf_l_b5]
+      end
+      def pdf_l_letter(fh=nil)
+        pdf_l(fh) + @md.fn[:pdf_l_letter]
+      end
+      def pdf_l_legal(fh=nil)
+        pdf_l(fh) + @md.fn[:pdf_l_legal]
+      end
+      def manpage(fh=nil)
+        fh=default_hash_build(fh,Sfx[:manpage])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def info(fh=nil)
+        fh=default_hash_build(fh,Sfx[:info])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def texinfo(fh=nil)
+        fh=default_hash_build(fh,Sfx[:texinfo])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def sqlite_discrete(fh=nil)
+        fh=default_hash_build(fh,Sfx[:sql])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh={
+          fn: fh[:fn],
+          ft: fh[:ft],
+          lng: fh[:lng],
+        }
+        i18n(fnh)
+      end
+      def hash_digest(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_language_code?
+          {
+            fn: fh[:fn] + '.hash_digest',
+            ft: fh[:ft],
+          }
+        elsif output_dir_structure.by_filetype?
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: 'digest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def sitemap(fh=nil)
+        fh=default_hash_build(fh,Sfx[:xml])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_language_code?
+          {
+            fn: fh[:fn] + '.sitemap',
+            ft: fh[:ft],
+          }
+        elsif output_dir_structure.by_filetype?
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: 'sitemap',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def qrcode_title(fh=nil)
+        fh=default_hash_build(fh,'.title.png')
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'sisu_manifest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def qrcode_md #check name below
+        fh=default_hash_build(fh,'.md.png')
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'sisu_manifest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def manifest_txt(fh=nil)
+        fh=default_hash_build(fh,Sfx[:txt])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.by_filename?
+          {
+            fn: 'sisu_manifest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def manifest(fh=nil)
+        fh=default_hash_build(fh,Sfx[:html])
+        fh[:lng]=lang_code?(fh[:lng])
+        fnh=if output_dir_structure.dump_or_redirect?
+          {
+            fn: fh[:fn] + '.manifest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        elsif output_dir_structure.by_filename?
+          {
+            fn: 'sisu_manifest',
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        else
+          {
+            fn: fh[:fn],
+            ft: fh[:ft],
+            lng: fh[:lng],
+          }
+        end
+        i18n(fnh)
+      end
+      def src
+        @md.fno
+      end
+      def po4a_cfg
+        'po4a.cfg'
+      end
+      def po #check
+        (@fno.empty?) \
+        ? (@md.fn[:po])
+        : (@fno + '.po')
+      end
+      def pot
+        (@fno.empty?) \
+        ? (@md.fn[:pot])
+        : (@fno + '.pot')
+      end
+      def po4a_sst #check
+        @fno
+      end
+      def sisupod
+        (@md.fns =~/\.ssm\.sst$/) \
+        ? @md.fns.gsub(/(?:\~\S{2,3})?\.ssm\.sst$/,'.ssm.txz')
+        : @md.fns.gsub(/(?:\~\S{2,3})?(\.sst)$/,'\1.txz')
+      end
+      self
+    end
+    def set_path(ft)
+      @ft=ft
+      def dir
+        def abc
+          if output_dir_structure.redirect?
+            @md.opt.opt_act[:redirect][:inst] + '/' + @md.fnb
+          elsif output_dir_structure.dump?
+            @md.opt.opt_act[:dump][:inst]
+          elsif output_dir_structure.by_language_code?
+            output_path.base.dir + '/' + @md.opt.lng + '/' + @ft
+          elsif output_dir_structure.by_filetype?
+            output_path.base.dir + '/' + @ft
+          else
+            output_path.base.dir + '/' + @md.fnb
+          end
+        end
+        def ab
+          if output_dir_structure.redirect?
+            @md.opt.opt_act[:redirect][:inst] + '/' + @md.fnb
+          elsif output_dir_structure.dump?
+            @md.opt.opt_act[:dump][:inst]
+          elsif output_dir_structure.by_language_code?
+            output_path.base.dir + '/' + @md.opt.lng + '/' + @ft
+          else
+            output_path.base.dir + '/' + @ft
+          end
+        end
+        def ab_src
+          if output_dir_structure.redirect?
+            @md.opt.opt_act[:redirect][:inst] + '/' + @md.fnb
+          elsif output_dir_structure.dump?
+            @md.opt.opt_act[:dump][:inst]
+          else
+            output_path.base.dir + '/' \
+              + @ft + '/' \
+              + @md.opt.fng + '/' \
+              + Gt[:sisupod] + '/' \
+              + Gt[:doc] + '/' \
+              + @md.opt.lng
+          end
+        end
+        def ab_pod
+          if output_dir_structure.redirect?
+            @md.opt.opt_act[:redirect][:inst] + '/' + @md.fnb
+          elsif output_dir_structure.dump?
+            @md.opt.opt_act[:dump][:inst]
+          else
+            output_path.base.dir + '/' + @ft
+          end
+        end
+        self
+      end
+      def url
+        def abc
+          if output_dir_structure.by_language_code?
+            output_path.base.url + '/' + @md.opt.lng + '/' + @ft
+          elsif output_dir_structure.by_filetype?
+            output_path.base.url + '/' + @ft
+          else
+            output_path.base.url + '/' + @md.fnb
+          end
+        end
+        def ab
+          if output_dir_structure.by_language_code?
+            output_path.base.url + '/' + @md.opt.lng + '/' + @ft
+          else
+            output_path.base.url + '/' + @ft
+          end
+        end
+        def ab_src
+          output_path.base.url + '/' \
+            + @ft + '/' \
+            + @md.opt.fng + '/' \
+            + Gt[:sisupod] + '/' \
+            + Gt[:doc] + '/' \
+            + @md.opt.lng
+        end
+        def ab_pod
+          output_path.base.url + '/' + @ft
+        end
+        self
+      end
+      def rel
+        def abc
+          if output_dir_structure.by_language_code?
+            @md.opt.lng + '/' + @ft
+          elsif output_dir_structure.by_filetype?
+            @ft
+          else
+            @md.fnb
+          end
+        end
+        def ab
+          if output_dir_structure.by_language_code?
+            @md.opt.lng + '/' + @ft
+          else
+            @ft
+          end
+        end
+        def ab_src
+          @ft
+        end
+        def ab_pod
+          @ft
+        end
+        self
+      end
+      def rel_sm
+        def abc
+          if output_dir_structure.by_language_code?
+            @md.opt.lng + '/' + @ft
+          elsif output_dir_structure.by_filetype?
+            @ft
+          else
+            @md.fnb
+          end
+        end
+        def ab
+          if output_dir_structure.dump_or_redirect?
+            '.'
+          elsif output_dir_structure.by_language_code? \
+          or output_dir_structure.by_filetype?
+            '../' + @ft
+          else '.'
+          end
+        end
+        def ab_src
+          locate="#{@ft}/#{@md.opt.fng}/#{Gt[:sisupod]}/#{Gt[:doc]}/#{@md.opt.lng}"
+          if output_dir_structure.dump_or_redirect?
+            '.'
+          elsif output_dir_structure.by_language_code?
+            '../../' + locate
+          else
+            '../' + locate
+          end
+        end
+        def ab_pod
+          if output_dir_structure.dump_or_redirect?
+            '.'
+          elsif output_dir_structure.by_language_code?
+            '../../' + @ft
+          else
+            '../' + @ft
+          end
+        end
+        self
+      end
+      def rcp
+        def abc
+          if output_dir_structure.by_language_code?
+            output_path.stub.rcp + '/' + @md.opt.lng + '/' + @ft
+          elsif output_dir_structure.by_filetype?
+            output_path.stub.rcp + '/' + @ft
+          else
+            output_path.stub.rcp + '/' + @md.fnb
+          end
+        end
+        def ab
+          if output_dir_structure.by_language_code?
+            output_path.stub.rcp + '/' + @md.opt.lng + '/' + @ft
+          else
+            output_path.stub.rcp + '/' + @ft
+          end
+        end
+        self
+      end
+      self
+    end
+    def output_path
+      def web_base
+        def dir
+          @env.path.webserv
+        end
+        def url
+          #"#{@env.url.root}"
+        end
+        def rel
+          '.'
+        end
+        def rcp
+          '.'
+        end
+        self
+      end
+      def stub
+        def dir
+          @md.opt.f_pth[:pth_stub]
+        end
+        #def url
+        #  "#{@env.url.root}"
+        #end
+        def rel
+          './' + @md.opt.f_pth[:pth_stub]
+        end
+        def rcp
+          @md.opt.f_pth[:pth_stub]
+        end
+        self
+      end
+      def webserver_path
+        if output_dir_structure.dump?
+          @md.opt.opt_act[:dump][:inst]
+        elsif output_dir_structure.redirect?
+          @md.opt.opt_act[:redirect][:inst]
+        else
+          @env.path.webserv
+        end
+      end
+      def base
+        def dir
+          webserver_path + '/' + @md.opt.f_pth[:pth_stub]
+        end
+        def url
+          @env.url.webserv + '/' + @md.opt.f_pth[:pth_stub]
+        end
+        def rel
+          './' + @md.opt.f_pth[:pth_stub]
+        end
+        def rcp
+          './' + @md.opt.f_pth[:pth_stub]
+        end
+        self
+      end
+      def sisugit
+        def dir
+          output_path.base.dir + '/git'
+        end
+        def url
+          output_path.base.url + '/git'
+        end
+        def rel
+          output_path.base.rel + '/git'
+        end
+        def rcp
+          output_path.base.rcp + '/git'
+        end
+        self
+      end
+      #def pod
+      #  ft='pod'
+      #  path=set_path(ft).dir.ab
+      #end
+      def src
+        def ft
+          Gt[:src]
+        end
+        def dir
+          set_path(ft).dir.ab_src
+        end
+        def url
+          set_path(ft).url.ab_src
+        end
+        def rel
+          set_path(ft).rel.ab_src
+        end
+        def rcp
+          set_path(ft).rcp.ab_src
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab_src
+        end
+        self
+      end
+      def sisupod
+        def ft
+          Gt[:src]
+        end
+        def dir
+          set_path(ft).dir.ab_pod
+        end
+        def url
+          set_path(ft).url.ab_pod
+        end
+        def rel
+          set_path(ft).rel.ab_pod
+        end
+        def rcp
+          set_path(ft).rcp.ab_pod
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab_pod
+        end
+        self
+      end
+      def po4a
+        def dir
+         output_path.base.dir + '/' \
+           + Gt[:src] + '/' \
+           + @md.opt.fng + '/po4a'
+        end
+        def url
+          output_path.base.url + '/po4a/' \
+            + @md.fnb
+        end
+        def rcp
+          #p "#{output_path.base.dir}/po4a/#{@md.fnb}"
+        end
+        self
+      end
+      def po(lng=@md.opt.lng)
+        @lng=lng
+        def dir
+          output_path.base.dir + '/' \
+            + Gt[:src] + '/' \
+            + @md.opt.fng + '/po4a/po/' \
+            + @lng
+        end
+        def url
+          output_path.base.url + '/po4a/' \
+            + @md.fnb + '/po/' \
+            + @lng
+        end
+        self
+      end
+      def pot
+        def dir
+         output_path.base.dir + '/' \
+           + Gt[:src] + '/' \
+           + @md.opt.fng + '/po4a/pot'
+        end
+        def url
+          output_path.base.url + '/po4a/' \
+            + @md.fnb + '/pot'
+        end
+        def rcp
+          #p "#{output_path.base.dir}/po4a/#{@md.fnb}/pot"
+        end
+        self
+      end
+      def po_git # consider !!!
+        def ft
+          Gt[:po]
+        end
+        def dir
+          pth=@env.processing_path.git + '/' \
+            + @md.fnb + '/' \
+            + ft + '/' \
+            + @md.opt.lng
+          FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+          pth
+        end
+        self
+      end
+      def pot_git # consider !!!
+        def ft
+          Gt[:pot]
+        end
+        def dir
+          @env.processing_path.git + '/' \
+            + @md.fnb + '/' \
+            + ft
+        end
+        self
+      end
+      def po4a_sst(lng=@md.opt.lng)
+        @lng=lng
+        def dir
+          output_path.base.dir + '/' \
+            + Gt[:src] + '/' \
+            + @md.opt.fng + '/po4a/' \
+            + @lng
+        end
+        def url
+          output_path.base.url + '/po4a/' \
+            + @md.fnb \
+            + @lng
+        end
+        self
+      end
+      def md_harvest
+        manifest
+        self
+      end
+      def txt
+        def ft
+          'txt'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def textile
+        def ft
+          'textile' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def asciidoc
+        def ft
+          'asciidoc' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def markdown
+        def ft
+          'markdown' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def rst
+        def ft
+          'rst' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def orgmode
+        def ft
+          'orgmode' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def html_scroll
+        def ft
+          'html'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          if output_dir_structure.dump_or_redirect?
+            './image'
+          elsif output_dir_structure.by_language_code?
+            '../../_sisu/image'
+          elsif output_dir_structure.by_filetype?
+            '../_sisu/image'
+          else
+            '../_sisu/image'
+          end
+        end
+        self
+      end
+      def html_seg
+        def ft
+          'html/' + @md.fnb
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          if output_dir_structure.dump_or_redirect?
+            './image'
+          elsif output_dir_structure.by_language_code?
+            '../../../_sisu/image'
+          elsif output_dir_structure.by_filetype?
+            '../../_sisu/image'
+          else
+            '../_sisu/image'
+          end
+        end
+        self
+      end
+      def html_concordance
+        html_seg
+        self
+      end
+      def html
+        def ft
+          'html'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).url.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          if output_dir_structure.by_language_code?
+            '../../_sisu/image'
+          elsif output_dir_structure.by_filetype?
+            '../_sisu/image'
+          else
+            '../_sisu/image'
+          end
+        end
+        self
+      end
+      def xhtml
+        def ft
+          'xhtml'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def epub
+        def ft
+          'epub'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          './image'
+        end
+        self
+      end
+      def odt
+        def ft
+          'odt'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def xml
+        def ft
+          'xml'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_sax
+        xml
+        self
+      end
+      def xml_dom
+        xml
+        self
+      end
+      def xml_docbook
+        def ft
+          'docbook'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_docbook_article
+        def ft
+          'docbook' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_docbook_book
+        def ft
+          'docbook'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_fictionbook
+        def ft
+          'fictionbook' \
+            + DEVELOPER[:under_construction]
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_scaffold_structure_sisu
+        def ft
+          'sisu.scaffold.xml'
+          #'xml'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def xml_scaffold_structure_collapse
+        def ft
+          'collapsed.scaffold.xml'
+          #'xml'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def json
+        def ft
+          'json'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        def rel_image
+          '../../_sisu/image'
+        end
+        self
+      end
+      def pdf
+        def ft
+          'pdf'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def sqlite_discrete
+        def ft
+          'sql'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def hash_digest
+        def ft
+          'hashes'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def manifest
+        def ft
+          'manifest'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rel_image
+          if output_dir_structure.dump_or_redirect?
+            './image'
+          elsif output_dir_structure.by_language_code?
+            '../../_sisu/image'
+          elsif output_dir_structure.by_filetype?
+            '../_sisu/image'
+          else
+            '../_sisu/image'
+          end
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        self
+      end
+      def qrcode
+        def ft
+          'manifest/qrcode'
+        end
+        def dir
+          set_path(ft).dir.abc
+        end
+        def url
+          set_path(ft).url.abc
+        end
+        def rel
+          set_path(ft).rel.abc
+        end
+        def rcp
+          set_path(ft).rcp.abc
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def harvest
+        def ft
+          'site_metadata'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        def rel_sm
+          if output_dir_structure.by_language_code?
+            ''
+          elsif output_dir_structure.by_filetype?
+            ''
+          else
+            ''
+          end
+        end
+        self
+      end
+      def manpage
+        def ft
+          'man'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def texinfo
+        def ft
+          'texinfo'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        def rel_sm
+          set_path(ft).rel_sm.ab
+        end
+        self
+      end
+      def sitemaps
+        def ft
+          'sitemaps'
+        end
+        def dir
+          set_path(ft).dir.ab
+        end
+        def url
+          set_path(ft).url.ab
+        end
+        def rel
+          set_path(ft).rel.ab
+        end
+        def rcp
+          set_path(ft).rcp.ab
+        end
+        self
+      end
+      def sqlite #check url
+        def dir
+          output_path.base.dir
+        end
+        def url
+          output_path.base.url
+        end
+        def rel
+          output_path.base.rel
+        end
+        def rcp
+          output_path.base.rcp
+        end
+        self
+      end
+      #def cgi
+      #end
+      def css
+        @d='_sisu/css'
+        def dir
+          output_path.base.dir + '/' + @d
+        end
+        def url
+          output_path.base.url + '/' + @d
+        end
+        def rel
+          @d
+          #output_path.base.rel + '/' + @d
+        end
+        def rcp
+          output_path.stub.rcp + '/' + @d
+        end
+        self
+      end
+      def images
+        @d='_sisu/image'
+        def dir
+          output_path.base.dir + '/' + @d
+        end
+        def url
+          output_path.base.url + '/' + @d
+        end
+        def rel
+          @d
+          #output_path.base.rel + '/' + @d
+        end
+        def rcp
+          output_path.stub.rcp + '/' + @d
+        end
+        self
+      end
+      def images_external
+        @d='_sisu/image_external'
+        def dir
+          output_path.base.dir + '/' + @d
+        end
+        def url
+          output_path.base.url + '/' + @d
+        end
+        def rel
+          output_path.base.rel + '/' + @d
+        end
+        def rcp
+          output_path.base.rcp + '/' + @d
+        end
+        self
+      end
+      #def css
+      #  #"#{@env.path.output}/#{@env.path.style}"
+      #end
+      self
+    end
+  end
+end
+module SiSU_Create_File
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class CreateFile < SiSU_Info_Env::InfoEnv                # se_info_env.rb
+    #todo unify with FileOp
+    def initialize(fns)
+      begin
+        super(fns)
+        @env=SiSU_Env::InfoEnv.new(fns)
+      rescue
+        SiSU_Screen::Ansi.new('',$!,$@).rescue do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      ensure
+      end
+    end
+    def html_root
+      #@env.path.output
+    end
+    def mkdir_pdf
+      Dir.mkdir(@env.processing_path.tex) \
+        unless FileTest.directory?(@env.processing_path.tex)
+    end
+    def file_generic(output_file='')
+      fn=@env.path.output + '/' \
+      + @fnb + '/' \
+      + output_file
+      File.new(fn,'w+')
+    end
+    def file_error
+      fn='/tmp/errorlog.sisu'
+      File.new(fn,'w+')
+    end
+    def file_txt
+      fn=@env.processing_path.ao + '/' \
+      + @fns + '.txt'
+      File.new(fn,'w+')
+    end
+    def file_debug
+      fn=@env.processing_path.ao + '/' \
+      + @fns + '.debug.txt'
+      File.new(fn,'w+')
+    end
+    def metaverse
+      def file_meta
+        fn=@env.processing_path.ao + '/' \
+        + @fns + '.meta'
+        File.new(fn,'w+')
+      end
+      def file_meta_idx_html
+        fn=@env.processing_path.ao + '/' \
+        + @fns + '.idx.html'
+        File.new(fn,'w+')
+      end
+      self
+    end
+    def file_note
+      fn=Dir.pwd + '/' \
+      + @fns + '.fn'
+      File.new(fn,'w+')
+    end
+    def meta
+      @env.processing_path.ao + '/' \
+      + @fns + '.meta'
+    end
+    def file_semantic
+      fn='./semantic.yaml'
+      File.new(fn,'w+')
+    end
+    def file_rss
+      fn='./semantic.xml'
+      File.new(fn,'w+')
+    end
+    def epub
+      @pth=@env.processing_path.epub
+      def xhtml_index
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/index.xhtml'
+        File.new(fn,'w+')
+      end
+      def xhtml_cover_image
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/cover_image.xhtml'
+        File.new(fn,'w+')
+      end
+      def xhtml_segtoc
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/toc.xhtml'
+        File.new(fn,'w+')
+      end
+      def mimetype  #fixed application/epub+zip ~/grotto/theatre/dbld/builds/epub_sample/mimetype
+        File.new("#{@pth}/mimetype",'w')
+      end
+      def metadata #variable matadata ~/grotto/theatre/dbld/builds/epub_sample/metadata.opf
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/' \
+        + Ep[:f_opf]
+        File.new(fn,'w')
+      end
+      def toc_ncx  #variable toc ~/grotto/theatre/dbld/builds/epub_sample/toc.ncx
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/' \
+        + Ep[:f_ncx]
+        File.new(fn,'w')
+      end
+      def metainf_cont #variable content ~/grotto/theatre/dbld/builds/epub_sample/META-INF/container.xml
+        fn=@pth + '/META-INF/container.xml'
+        File.new(fn,'w')
+      end
+      def xhtml_css #fixed epub xhtml css
+        fn=@pth + '/' \
+        + Ep[:d_oebps] + '/css/xhtml.css'
+        File.new(fn,'w')
+      end
+      self
+    end
+    def file_texinfo
+      fn=@env.processing_path.texinfo + '/' \
+      + @fnb + '.texinfo'
+      File.new(fn,'w+')
+    end
+  end
+end
+module SiSU_Filename_Lang
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class FilenameLanguageCodeInsert
+    def initialize(opt,lng=nil)
+      @opt=opt
+      @lng=lng ||=opt.lng
+    end
+    def language_code_insert
+      if @opt.dir_structure_by ==:language \
+      or ((@opt.dir_structure_by ==:filetype \
+      || @opt.dir_structure_by ==:filename) \
+      and (@opt.lingual ==:mono \
+      && @lng == @opt.act[:default_language][:code]))
+        ''
+      elsif (@opt.dir_structure_by ==:filetype \
+      || @opt.dir_structure_by ==:filename) \
+      and not @opt.lingual ==:mono
+        '.' + @lng
+      else
+        '.' + @lng
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_get_init.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_get_init.rb"
+# <>
+module SiSU_Get_Init
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_system'                        # se_info_system.rb
+  @@noyaml=false
+  class GetInit < SiSU_Info_Sys_Gen::InfoSystemGen         # se_info_system.rb
+    @@noyaml=false
+    @@rc,@@sisu_doc_makefile,@@sisurc_path,@@tx=nil,nil,nil,nil
+    @@ad={ promo: nil, promo_list: nil, flag_promo: false }
+    @@sdmd=nil
+    attr_accessor :yaml
+    def initialize
+      super()
+        @markup_dir_changed_=if @@sdmd==$sisu_document_markup_directory
+          false
+        else
+          @@sdmd=$sisu_document_markup_directory
+          true
+        end
+    end
+    def tex
+      require_relative 'texpdf_parts'                        # texpdf_parts.rb
+      @@tx ||=SiSU_Parts_TeXpdf::TeX.new
+    end
+    def rc_path_options
+      v=SiSU_Env::InfoVersion.instance.get_version
+      [
+        $sisu_document_markup_directory_base_fixed_path \
+        + '/.sisu/v' \
+        + v.version_major,
+        $sisu_document_markup_directory_base_fixed_path \
+        + '/.sisu',
+        $sisu_document_markup_directory_base_fixed_path \
+        + '/_sisu/v' \
+        + v.version_major,
+        $sisu_document_markup_directory_base_fixed_path \
+        + '/_sisu',
+        @@home \
+        + '/.sisu/v' \
+        + v.version_major,
+        @@home \
+        + '/.sisu', \
+        @@sisu_etc \
+        + '/v' \
+        + v.version_major,
+        @@sisu_etc,
+      ]
+    end
+    def sisu_document_make
+      def makefile_name
+        S_CONF[:header_make]
+      end
+      def makefile
+        rc_path_options.each do |v|
+          if FileTest.exist?("#{v}/#{makefile_name}")
+            @sisu_make_path=v
+            break
+          end
+        end
+        @sisu_make_file_path=@sisu_make_path \
+        ? "#{@sisu_make_path}/#{makefile_name}"
+        : nil
+      end
+      def makefile_read
+        if makefile
+          sisu_doc_makefile=IO.read(makefile, mode: 'r:utf-8')
+          @sisu_doc_makefile=sisu_doc_makefile.split(/\s*\n\s*\n/m)
+        end
+        @sisu_doc_makefile
+      end
+      self
+    end
+    def sisu_yaml
+      def rc
+        if @markup_dir_changed_
+          rc_path_options.each do |v|
+            if @@noyaml \
+            or FileTest.exist?("#{v}/noyaml")
+              STDERR.puts "WARNING - YAML loading switched off, to enable delete the file:\n\t#{v}/noyaml\n\n" unless @@noyaml
+              @@noyaml=true
+              break
+            else
+              f=S_CONF[:rc_yml]
+              p_f="#{v}/#{f}"
+              if FileTest.exist?(p_f)
+                begin
+                  require 'yaml'
+                rescue LoadError
+                  SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                    error('yaml NOT FOUND (LoadError)')
+                end
+                @@sisurc_path=v
+                @@rc=YAML::load(File::open(p_f))
+                break
+              end
+              unless @@rc
+                f='sisurc.yaml'
+                p_f="#{v}/#{f}"
+                if FileTest.exist?(p_f)
+                  begin
+                    require 'yaml'
+                  rescue LoadError
+                    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                      error('yaml NOT FOUND (LoadError)')
+                  end
+                  @@sisurc_path=v
+                  @@rc=YAML::load(File::open(p_f))
+                  break
+                end
+              end
+            end
+          end
+        end
+        @@rc
+      end
+      def rc_path
+        rc
+        @@sisurc_path
+      end
+      self
+    end
+    def ads #WORK AREA
+      tell_no_yaml='WARNING - YAML loading switched off, to enable delete the file:'
+      if @markup_dir_changed_
+        @ad_path=[
+          "#{$sisu_document_markup_directory_base_fixed_path}/.sisu/skin/yml",
+          "#{$sisu_document_markup_directory_base_fixed_path}/_sisu/skin/yml",
+          "#{@@home}/.sisu/skin/yml",
+          "#{@@sisu_etc}/skin/yml",
+        ]
+        @ad_path.each do |v|
+          if @@noyaml \
+          or FileTest.exist?("#{v}/noyaml")
+            puts tell_no_yaml + "\n\t#{v}/noyaml\n" unless @@noyaml
+            @@noyaml=true
+            break
+          else
+            if FileTest.exist?("#{v}/list.yml")
+              unless @@ad[:promo_list]
+                begin
+                  require 'yaml'
+                rescue LoadError
+                  SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                    error('yaml NOT FOUND (LoadError)')
+                end
+                @@ad[:promo_list] ||= YAML::load(File::open("#{v}/list.yml"))
+              end
+              @@ad[:flag_promo]=true
+              break
+            end
+            @@ad[:flag_promo]=false
+          end
+        end
+        @ad_path.each do |v|
+          if @@noyaml \
+          or FileTest.exist?("#{v}/noyaml")
+            puts tell_no_yaml + "\n\t#{v}/noyaml\n" unless @@noyaml
+            @@noyaml=true
+            break
+          else
+            if FileTest.exist?("#{v}/promo.yml")
+              unless @@ad[:promo]
+                begin
+                  require 'yaml'
+                rescue LoadError
+                  SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+                    error('yaml NOT FOUND (LoadError)')
+                end
+                @@ad[:promo] ||= YAML::load(File::open("#{v}/promo.yml"))
+              end
+              @@ad[:flag_promo]=true
+              break
+            end
+            @@ad[:flag_promo]=false
+          end
+        end
+      end
+      @@ad
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_hub_particulars.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_hub_particulars.rb"
+# <>
+module SiSU_Particulars
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  require_relative 'se'                                 # se.rb
+    include SiSU_Env
+  require_relative 'dp'                                 # dp.rb
+    include SiSU_Param
+  require_relative 'ao'                                 # ao.rb
+  class CombinedSingleton
+    include Singleton
+    def get_all(opt)
+      set_env(opt)
+      set_file(opt)
+      set_md(opt)
+      set_ao(opt)                #needs @md
+    end
+    def get_env(opt)
+      set_env(opt)
+    end
+    def get_file(opt)
+      set_file(opt)
+    end
+    def get_md(opt)
+      set_md(opt)
+    end
+    def get_ao_array(opt)
+      set_ao(opt)                #needs @md
+    end
+    def get_env_md(opt)
+      set_env(opt)
+      set_md(opt)
+    end
+    def get_idx_sst(opt)
+      set_sst_idx(opt)
+    end
+    def get_idx_raw(opt)
+      set_raw_idx(opt)
+    end
+    def get_idx_html(opt)
+      set_html_idx(opt)
+    end
+    def get_idx_xhtml(opt)
+      set_xhtml_idx(opt)
+    end
+    def get_name_tags(opt)
+      set_name_tags(opt)
+    end
+    def get_maps(opt)
+      set_nametags_map(opt)
+      set_ocn_htmlseg_map(opt)
+    end
+    def get_map_nametags(opt)
+      set_nametags_map(opt)
+    end
+    def get_map_ocn_htmlseg(opt)
+      set_ocn_htmlseg_map(opt)
+    end
+    attr_accessor :opt,:md,:sst_idx,:raw_idx,:html_idx,:xhtml_idx
+    def set_md(opt)
+      begin
+        @md=SiSU_Param::Parameters.new(opt).get
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    attr_accessor :opt,:env,:file
+    def set_env(opt)
+      begin
+        @env=SiSU_Env::InfoEnv.new(opt.fns)
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def set_file(opt)
+      begin
+        set_md(opt) unless @md
+        @file=SiSU_Env::FileOp.new(@md)
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    attr_accessor :opt,:ao_array
+    def set_ao(opt)
+      begin
+        @ao_array=SiSU_AO::Source.new(opt).get
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def set_sst_idx(opt)
+      begin
+        @sst_idx=SiSU_AO::Source.new(opt).get_idx_sst
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def set_raw_idx(opt)
+      begin
+        @raw_idx=SiSU_AO::Source.new(opt).get_idx_raw
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def set_html_idx(opt)
+      begin
+        @html_idx=SiSU_AO::Source.new(opt).get_idx_html
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    def set_xhtml_idx(opt)
+      begin
+        @xhtml_idx=SiSU_AO::Source.new(opt).get_idx_xhtml
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+    attr_accessor :nametags_map
+    def set_nametags_map(opt)
+      begin
+        opt=@md ? @md : opt
+        @nametags_map=SiSU_AO::Source.new(opt).get_map_nametags
+        self
+      rescue
+        if @md
+          SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.opt.fnl).location do
+            __LINE__.to_s + ':' + __FILE__
+          end
+        else
+          SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+            __LINE__.to_s + ':' + __FILE__
+          end
+        end
+      end
+    end
+    attr_accessor :ocn_htmlseg_map
+    def set_ocn_htmlseg_map(opt)
+      begin
+        @ocn_htmlseg_map=SiSU_AO::Source.new(@md).get_map_ocn_htmlseg
+        self
+      rescue
+        SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fnl).location do
+          __LINE__.to_s + ':' + __FILE__
+        end
+      end
+    end
+  end
+end
+__END__
+consider running as separate objects
+#+END_SRC
+
+** se_info_env.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_info_env.rb"
+# <>
+@@current_document=Dir.pwd #nil #''
+module SiSU_Info_Env
+  require_relative 'se_envcall'                            # se_envcall.rb
+  require_relative 'html_parts'                            # html_parts.rb
+  begin
+    require 'singleton'
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton or fileutils NOT FOUND (LoadError)')
+  end
+  class InfoEnv < SiSU_Env_Call::EnvCall                   # se_envcall.rb
+    begin
+      require 'pathname'
+      require 'fileutils'
+        include FileUtils
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('pathname or fileutils NOT FOUND (LoadError)')
+    end
+    attr_accessor :filename,:sys,:home,:hostname,:user,:env,:rc,:www,:fnb,:fnn,:fnt,:flv,:webserv_path,:stub_pwd,:base_markup_dir_stub,:stub_src,:webserv_host_cgi,:webserv_port_cgi,:processing,:processing_git,:etc,:yamlrc_dir
+    @@image_flag,@@local_image=true,true   #warning on @@image_flag
+    @@fb,@@man_path=nil,nil
+    def initialize(fns='',md=nil)
+      super() #you may not want to re-execute this static info so frequently!
+      @init=SiSU_Env::GetInit.new #SiSU_Get_Init::GetInit
+      @fns,@md=fns,md
+      @env=SiSU_Env::EnvCall.new(fns) if fns #SiSU_Env_Call::EnvCall
+      fnb=if @md \
+      and defined? @md.fnb
+        @md.fnb
+      elsif defined? @env.fnb \
+      and @env.fnb
+        @env.fnb
+      elsif @fns.is_a?(String) \
+      and not @fns.empty?
+        m=/(.+)?\.(?:(?:-|ssm\.)?sst|ssm)$/m
+        @fns[m,1] if not @fns.empty?
+      end
+      if fnb; @@fb ||=fnb
+      end
+      @sys=SiSU_Info_Sys::InfoSystem.instance
+      @fnb ||=@@fb #clean up this... used primarily for zap which is not passed normal parameters
+      @fixed_websev_root='' # @home
+      @pwd=@@pwd=Dir.pwd
+      @base_markup_dir_stub=SiSU_Utils::Path.new.base_markup_stub
+      @stub_src=     @base_markup_dir_stub + '/src'
+      @stub_pod=     @base_markup_dir_stub + '/pod'
+      @stub_epub=    @base_markup_dir_stub + '/epub'
+      m=/.+\/(?:src\/)?(\S+)/m # m=/.+?\/(?:src\/)?([^\/]+)$/im # m=/.+\/(\S+)/m
+      @stub_pwd=@@pwd[m,1] || '' #; p __LINE__; #p @pwd; #p m; #p @stub_pwd
+      pt=Pathname.new(Dir.pwd)
+      stub=if output_dir_structure.by_language_code?
+        r=Px[:lng_lst_rgx]
+        stub=if Dir.pwd =~/.+?\/([^\/]+)(?:\/(#{r})$)/
+          lng=pt.split[-1].to_s
+          lng_part='/' + lng
+          base=pt.split[0].split[-1].to_s
+        else
+          lng_part='/' + language_default_set
+          base=pt.split[-1].to_s
+        end
+        base + lng_part
+      elsif output_dir_structure.by_filetype?
+        pt.split[-1].to_s
+      elsif  output_dir_structure.by_filename?
+        ''
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn('set output type, by: language, filetype or filename')
+      end
+      @stub_set_manifest=stub + '/manifest'
+    end
+    def user
+      @sys.user
+    end
+    def hostname
+      @sys.hostname
+    end
+    def host
+      @sys.host
+    end
+    def arch
+      @sys.arch
+    end
+    def rbver
+      @sys.rbver
+    end
+    def locale
+      @sys.locale
+    end
+    def concord_max
+      ((defined? @rc['processing']['concord_max']) \
+      && @rc['processing']['concord_max']) \
+      ? @rc['processing']['concord_max']
+      : (defaults[:concord_max])
+    end
+    def language_default_set           #set directory (default) language
+      ((defined? @rc['default']['language']) \
+      && @rc['default']['language'] =~/\S+/) \
+      ? @rc['default']['language']
+      : 'en'
+    end
+    def markup_emphasis
+      if defined? @rc['default']['emphasis'] \
+      and @rc['default']['emphasis'] \
+      and @rc['default']['emphasis']=~/bold/
+        'bold'
+      elsif defined? @rc['default']['emphasis'] \
+      and @rc['default']['emphasis'] \
+      and @rc['default']['emphasis']=~/italic/
+        'italics'
+      elsif defined? @rc['default']['emphasis'] \
+      and @rc['default']['emphasis'] \
+      and @rc['default']['emphasis']=~/underscore/
+        'underscore'
+      else 'bold'
+      end
+    end
+    def plaintext_wrap
+      ((defined? @rc['default']['text_wrap']) \
+      && (@rc['default']['text_wrap']) \
+      && (@rc['default']['text_wrap'].to_s=~/\d\d+/) \
+      && (@rc['default']['text_wrap'].to_i > 19) \
+      && (@rc['default']['text_wrap'].to_i < 201)) \
+      ? @rc['default']['text_wrap'].to_i
+      : 78
+    end
+    def current_document
+      @@current_document||=Dir.pwd
+      @@current_document
+    end
+    def stub_pwd                       #200412
+      @stub_pwd
+    end
+    def base_markup_dir_stub
+      @base_markup_dir_stub
+    end
+    def stub_md_harvest                #watch
+      @stub_set_manifest
+    end
+    def stub_src
+      @stub_src
+    end
+    def stub_pod
+      @stub_pod
+    end
+    def sisupod_v4(opt)
+      #processing_path.processing
+      #  sisupod
+      #    doc/
+      #      manifest.txt
+      #      en/content.sst                [file content]
+      #      fr/content.sst
+      #      _sisu
+      #        sisu_document_make
+      #        image@ (ln -s ../../image)
+      #        audio@ (ln -s ../../audio)
+      #        video@ (ln -s ../../video)
+      #    image/                          [all images for specific document gathered here]
+      #    audio/
+      #    video/
+      spp="#{processing_path.processing}/#{Gt[:sisupod]}"
+      sppc="#{spp}/doc/_sisu"
+      lng_dirs=[]
+      if FileTest.directory?(spp) \
+      or FileTest.file?(spp)
+        FileUtils::rm_rf(spp)
+      end
+      paths=[]
+      flv=SiSU_Env::EnvCall.new(opt.fns).
+        document_language_versions_found
+      flv[:f].each {|l| lng_dirs << l[:l] }
+      lng_dirs.uniq.each do |lng|
+        paths << "#{spp}/doc/#{lng}"
+      end
+      paths \
+      << "#{spp}/image"
+     #<< "#{spp}/audio" \
+     #<< "#{spp}/video" \
+      paths.each do |x|
+        unless FileTest.directory?(x)
+          FileUtils::mkdir_p(x)
+        end
+      end
+      if FileTest.directory?(sppc)
+        pwd=Dir.pwd
+        Dir.chdir(sppc)
+        FileUtils::ln_s('../../image', 'image')
+       #FileUtils::ln_s('../../audio', 'audio')
+       #FileUtils::ln_s('../../video', 'video')
+        Dir.chdir(pwd)
+      end
+    end
+    def sisupod_v3(opt)
+      #processing_path.processing
+      #  sisupod
+      #    doc/
+      #      manifest.txt
+      #      en/content.sst                [file content]
+      #      fr/content.sst
+      #      _sisu
+      #        skin/
+      #          doc                       [relevant skin if any other than default]
+      #        image@ (ln -s ../../image)
+      #        audio@ (ln -s ../../audio)
+      #        video@ (ln -s ../../video)
+      #    image/                          [all images for specific document gathered here]
+      #    audio/
+      #    video/
+      spp="#{processing_path.processing}/#{Gt[:sisupod]}"
+      sppc="#{spp}/doc/_sisu"
+      lng_dirs=[]
+      if FileTest.directory?(spp) \
+      or FileTest.file?(spp)
+        FileUtils::rm_rf(spp)
+      end
+      paths=[]
+      flv=SiSU_Env::EnvCall.new(opt.fns).
+        document_language_versions_found
+      flv[:f].each {|l| lng_dirs << l[:l] }
+      lng_dirs.uniq.each do |lng|
+        paths << "#{spp}/doc/#{lng}"
+      end
+      paths \
+      << "#{spp}/image" \
+      << "#{sppc}/skin/doc" \
+      << "#{sppc}/skin/dir" \
+      << "#{sppc}/skin/site"
+     #<< "#{spp}/audio" \
+     #<< "#{spp}/video" \
+      paths.each do |x|
+        unless FileTest.directory?(x)
+          FileUtils::mkdir_p(x)
+        end
+      end
+      if FileTest.directory?(sppc)
+        pwd=Dir.pwd
+        Dir.chdir(sppc)
+        FileUtils::ln_s('../../image', 'image')
+       #FileUtils::ln_s('../../audio', 'audio')
+       #FileUtils::ln_s('../../video', 'video')
+        Dir.chdir(pwd)
+      end
+    end
+    def sisupod_v2
+      #processing_path.processing
+      #  sisupod
+      #    content.sst              [file content]
+      #    filename.sst             [link to content.sst]
+      #    _sisu
+      #      skin/
+      #        doc                  [relevant skin if any other than default]
+      #      image                  [all images for specific document gathered here]
+      sisupod_processing_path="#{processing_path.processing}/#{Gt[:sisupod]}"
+      if FileTest.directory?(sisupod_processing_path) \
+      or FileTest.file?(sisupod_processing_path)
+        FileUtils::rm_rf(sisupod_processing_path)
+      end
+      paths=[]
+      paths=[
+        "#{processing_path.processing}/#{Gt[:sisupod]}/_sisu/skin/doc",
+        "#{processing_path.processing}/#{Gt[:sisupod]}/_sisu/skin/dir",
+        "#{processing_path.processing}/#{Gt[:sisupod]}/_sisu/skin/site",
+        "#{processing_path.processing}/#{Gt[:sisupod]}/_sisu/image"
+      ]
+      paths.each {|x| FileUtils::mkdir_p(x) unless FileTest.directory?(x) }
+    end
+    def defaults                       #multiple default directories
+      @default_dir ||=@sys.default_dir #DEFAULT_DIR
+    end
+    def html_seg_title_banner?
+      ((defined? @rc['html']['seg_title_banner']) \
+      && @rc['html']['seg_title_banner']==true) \
+      ? @rc['html']['seg_title_banner']
+      : false
+    end
+    def html_quick_ref?
+      ((defined? @rc['html']['quick_ref']) \
+      && @rc['html']['quick_ref']==true) \
+      ? @rc['html']['quick_ref']
+      : false
+    end
+    def html_minitoc?
+      if defined? @rc['html']['minitoc'] \
+      and @rc['html']['minitoc'].is_a?(String)
+        @rc['html']['minitoc']
+      else false
+      end
+    end
+    def manifest_minitoc?
+      if defined? @rc['manifest']['minitoc'] \
+      and @rc['manifest']['minitoc'].is_a?(String)
+        @rc['manifest']['minitoc']
+      else false
+      end
+    end
+    def build
+      def omit_list
+        @off_list ||=if defined? @rc['omit_list'] \
+        and @rc['omit_list'].is_a?(String)
+          @rc['omit_list']
+        elsif defined? @rc['omit']['list'] \
+        and @rc['omit']['list'].is_a?(String)
+          @rc['omit']['list']
+        else
+          nil
+        end
+      end
+      def listed?(test) #fix
+        listed=if omit_list
+          x=(omit_list.scan(/\b#{test}\b/)).join
+          test==x \
+          ? true
+          : false
+        else
+          false
+        end
+        listed
+      end
+      def ocn?
+        if (defined? @rc['omit']['ocn'] \
+        and not @rc['omit']['ocn'].nil?) \
+        or listed?('ocn')
+          :off
+        else
+          :na
+        end
+      end
+      def toc?
+        if (defined? @rc['omit']['toc'] \
+        and not @rc['omit']['toc'].nil?) \
+        or listed?('toc')
+          :off
+        else
+          :na
+        end
+      end
+      def manifest?
+        if (defined? @rc['omit']['manifest'] \
+        and not @rc['omit']['manifest'].nil?) \
+        or listed?('manifest')
+          :off
+        else
+          :na
+        end
+      end
+      def links_to_manifest?
+        if (defined? @rc['omit']['links_to_manifest'] \
+        and not @rc['omit']['links_to_manifest'].nil?) \
+        or (listed?('links_to_manifest') \
+        ||  listed?('manifest_links'))
+          :off
+        else
+          :na
+        end
+      end
+      def metadata?
+        if (defined? @rc['omit']['metadata'] \
+        and not @rc['omit']['metadata'].nil?) \
+        or listed?('metadata')
+          :off
+        else
+          :na
+        end
+      end
+      def minitoc?
+        if (defined? @rc['omit']['minitoc'] \
+        and not @rc['omit']['minitoc'].nil?) \
+        or (listed?('minitoc'))
+          :off
+        else
+          :na
+        end
+      end
+      def manifest_minitoc?
+        if (defined? @rc['omit']['manifest_minitoc'] \
+        and not @rc['omit']['manifest_minitoc'].nil?) \
+        or listed?('manifest_minitoc')
+          :off
+        else
+          :na
+        end
+      end
+      def html_minitoc?
+        if (defined? @rc['omit']['html_minitoc'] \
+        and not @rc['omit']['html_minitoc'].nil?) \
+        or (listed?('html_minitoc') \
+        || listed?('minitoc'))
+          :off
+        else
+          :na
+        end
+      end
+      def html_navigation?
+        if (defined? @rc['omit']['html_navigation'] \
+        and not @rc['omit']['html_navigation'].nil?) \
+        or listed?('html_navigation')
+          :off
+        else
+          :na
+        end
+      end
+      def html_navigation_bar?
+        if (defined? @rc['omit']['html_navigation_bar'] \
+        and not @rc['omit']['html_navigation_bar'].nil?) \
+        or listed?('html_navigation_bar')
+          :off
+        else
+          :na
+        end
+      end
+      def segsubtoc?
+        if (defined? @rc['omit']['segsubtoc'] \
+        and not @rc['omit']['segsubtoc'].nil?) \
+        or listed?('segsubtoc')
+          :off
+        else
+          :na
+        end
+      end
+      def html_right_pane?
+        if (defined? @rc['omit']['html_right_pane'] \
+        and not @rc['omit']['html_right_pane'].nil?) \
+        or listed?('html_right_pane')
+          :off
+        else
+          :na
+        end
+      end
+      def html_top_band?
+        if (defined? @rc['omit']['html_top_band'] \
+        and not @rc['omit']['html_top_band'].nil?) \
+        or listed?('html_top_band')
+          :off
+        else
+          :na
+        end
+      end
+      def search_form? #decide later, as is configured here (in sisurc) and can be turned off on command line
+        if (defined? @rc['omit']['search_form'] \
+        and not @rc['omit']['search_form'].nil?) \
+        or listed?('search_form')
+          :off
+        else
+          :na
+        end
+      end
+      def html_search_form? #decide later, as is configured here (in sisurc) and can be turned off on command line
+        if (defined? @rc['omit']['html_search_form'] \
+        and not @rc['omit']['html_search_form'].nil?) \
+        or listed?('html_search_form')
+          :off
+        else
+          :na
+        end
+      end
+      self
+    end
+    def odt_ocn?
+      ((defined? @rc['odt']['ocn']) \
+      && @rc['odt']['ocn']==false) \
+      ? @rc['odt']['ocn']
+      : true
+    end
+    def xml_docbook_ocn?
+      ((defined? @rc['xml_docbook']['ocn']) \
+      && @rc['xml_docbook']['ocn']==false) \
+      ? @rc['xml_docbook']['ocn']
+      : true
+    end
+    def xml_fictionbook_ocn?
+      ((defined? @rc['xml_fictionbook']['ocn']) \
+      && @rc['xml_fictionbook']['ocn']==false) \
+      ? @rc['xml_fictionbook']['ocn']
+      : true
+    end
+    def xml_scaffold_ocn?
+      ((defined? @rc['xml_scaffold']['ocn']) \
+      && @rc['xml_scaffold']['ocn']==false) \
+      ? @rc['xml_scaffold']['ocn']
+      : true
+    end
+    def plaintext_ocn?
+      ((defined? @rc['plaintext']['ocn']) \
+      && @rc['plaintext']['ocn']==false) \
+      ? @rc['plaintext']['ocn']
+      : true
+    end
+    def textile_ocn?
+      ((defined? @rc['textile']['ocn']) \
+      && @rc['textile']['ocn']==true) \
+      ? @rc['textile']['ocn']
+      : false
+    end
+    def asciidoc_ocn?
+      ((defined? @rc['asciidoc']['ocn']) \
+      && @rc['asciidoc']['ocn']==true) \
+      ? @rc['asciidoc']['ocn']
+      : false
+    end
+    def markdown_ocn?
+      ((defined? @rc['markdown']['ocn']) \
+      && @rc['markdown']['ocn']==true) \
+      ? @rc['markdown']['ocn']
+      : false
+    end
+    def rst_ocn?
+      ((defined? @rc['rst']['ocn']) \
+      && @rc['rst']['ocn']==true) \
+      ? @rc['rst']['ocn']
+      : false
+    end
+    def orgmode_ocn?
+      ((defined? @rc['orgmode']['ocn']) \
+      && @rc['orgmode']['ocn']==true) \
+      ? @rc['orgmode']['ocn']
+      : false
+    end
+    def widget #needs (md) #move
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @ad=SiSU_Env::GetInit.new.ads
+      @html_bits=SiSU_Proj_HTML::Bits.new
+      @flag={
+        ad: false,
+        md: false,
+        sk: false,
+        rc: false
+      }
+      def promo?
+        @flag[:ad]=if @md.flag_promo \
+        && @ad[:flag_promo]
+          @flag[:md]=true
+          true
+        elsif defined? @html_bits.widget_promo \
+        and not @html_bits.widget_promo.nil? \
+        and @html_bits.widget_promo.is_a?(Array) \
+        and @html_bits.widget_promo.length > 0
+          @flag[:sk]=true
+          true
+        elsif defined? @rc['html']['promo'] \
+        and not @rc['html']['promo'].nil? \
+        and @rc['html']['promo'].length > 0
+          @flag[:rc]=true
+          true
+        else false
+        end
+        @flag
+      end
+      def search?
+        searches=['sisu']
+        flag=false
+        if defined? @rc['search']
+          searches.each do |type|
+            flag=if defined? @rc['search'][type] \
+            and defined? @rc['search'][type]['action'] \
+            and @rc['search'][type]['flag']==true \
+            and @rc['search'][type]['action'] =~/https?:\/\//
+              flag=if promo?[:ad]
+                false
+              elsif defined? @html_bits.widget_search \
+              and @html_bits.widget_search==true
+                true
+              elsif defined? @rc['search'][type]['flag'] \
+              and @rc['search'][type]['flag']==true
+                true
+              else false
+              end
+            else false
+            end
+          end
+        else false
+        end
+        flag
+      end
+      def search_fixed?
+        searches=['sisu','hyperestraier']
+        flag=if defined? @rc['search']
+          searches.each do |type|
+            if defined? @rc['search'][type] \
+            and defined? @rc['search'][type]['action'] \
+            and @rc['search'][type]['action'] =~/https?:\/\// \
+            and defined? @rc['search'][type]['db'] \
+            and @rc['search'][type]['db'] =~/\S+/
+              flag=if promo?[:ad]
+                false
+              elsif defined? @html_bits.widget_search \
+              and @html_bits.widget_search==true
+                true
+              elsif defined? @rc['search'][type]['flag'] \
+              and @rc['search'][type]['flag']==true
+                true
+              else false
+              end
+            else false
+            end
+          end
+        else false
+        end
+      end
+      def search_form(type='sisusearch',action=nil,db=nil,table=false)
+        rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+        create_form_sisu=if action \
+        and db \
+        and action =~/https?:\/\// \
+        and db =~/\S+/
+          true
+        elsif widget.search?
+          db=if rc['search']['sisu']['flag']==true \
+          and rc['search']['sisu']['db']=~/\S+/
+            (rc['search']['sisu']['db']=~/^#{Db[:name_prefix]}\S+/) \
+            ? rc['search']['sisu']['db']
+            : "#{Db[:name_prefix]}#{rc['search']['sisu']['db']}"
+          else nil
+          end
+          action=rc['search']['sisu']['action']
+          true
+        elsif defined? rc['search']['sisu']['flag'] \
+        and defined? rc['search']['sisu']['action'] \
+        and rc['search']['sisu']['flag']==true \
+        and rc['search']['sisu']['action'] =~/https?:\/\//
+          true
+        else false
+        end
+        if table
+          table_open=''
+          table_close=' '
+        else
+          table_open=''
+          table_close=' '
+        end
+        form=if create_form_sisu \
+        and type=~/sisusearch/ \
+        and defined? rc['search']['sisu'] \
+        and defined? rc['search']['sisu']['action']
+          <
+#{table_open}
+ 
+
+#{table_close}
+
+WOK
+        else ''
+        end
+        form
+      end
+      def search_form_static(action=nil,db=nil)
+        rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+        create_form=if rc['search']['sisu']['flag']==true \
+        and action \
+        and db \
+        and action =~/https?:\/\// \
+        and db =~/\S+/
+          true
+        elsif widget.search_fixed?
+          db=if rc['search']['sisu']['flag']==true \
+          and rc['search']['sisu']['db']=~/\S+/
+            (rc['search']['sisu']['db']=~/^#{Db[:name_prefix]}\S+/) \
+            ? rc['search']['sisu']['db']
+            : "#{Db[:name_prefix]}#{rc['search']['sisu']['db']}"
+          else nil
+          end
+          action=rc['search']['sisu']['action']
+          true
+        else false
+        end
+        if create_form
+          %{
+
+ 
+
+
+  }
+        else ''
+        end
+      end
+      def search_action #check
+        if search?
+        else ''
+        end
+      end
+      self
+    end
+    def widget_static
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @html_bits=SiSU_Proj_HTML::Bits.new
+      @flag={ ad: false, md: false, sk: false, rc: false }
+      def search?
+        flag=if defined? @rc['search'] \
+        and defined? @rc['search']['sisu'] \
+        and defined? @rc['search']['sisu']['action'] \
+        and @rc['search']['sisu']['action'] =~/https?:\/\// \
+        and defined? @rc['search']['sisu']['db'] \
+        and @rc['search']['sisu']['db'] =~/\S+/
+          flag=if defined? @html_bits.widget_search \
+          and @html_bits.widget_search==true
+            true
+          elsif defined? @rc['search']['sisu']['flag'] \
+          and @rc['search']['sisu']['flag']==true
+            true
+          else
+            false
+          end
+        else
+          false
+        end
+      end
+      def search_fixed?
+        flag=if defined? @rc['search'] \
+        and defined? @rc['search']['sisu'] \
+        and defined? @rc['search']['sisu']['action'] \
+        and @rc['search']['sisu']['action'] =~/https?:\/\// \
+        and defined? @rc['search']['sisu']['db'] \
+        and @rc['search']['sisu']['db'] =~/\S+/ \
+        and defined? @rc['search']['sisu']['db'] \
+        and @rc['search']['sisu']['db'] =~/\S+/
+          flag=if defined? @html_bits.widget_search \
+          and @html_bits.widget_search==true
+            true
+          elsif defined? @rc['search']['sisu']['flag'] \
+          and @rc['search']['sisu']['flag']==true
+            true
+          else
+            false
+          end
+        else
+          false
+        end
+      end
+      def search_form(action=nil,db=nil)
+        rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+        create_form=if defined? rc['search']['sisu']['flag'] \
+        and rc['search']['sisu']['flag']==true \
+        and action \
+        and db \
+        and action =~/https?:\/\// \
+        and db =~/\S+/
+          true
+        elsif widget_static.search? \
+        and rc['search']['sisu']['flag']==true
+          db=if rc['search']['sisu']['db']=~/\S+/
+            (rc['search']['sisu']['db']=~/^#{Db[:name_prefix]}\S+/) \
+            ? rc['search']['sisu']['db']
+            : "#{Db[:name_prefix]}#{rc['search']['sisu']['db']}"
+          else nil
+          end
+          action=rc['search']['sisu']['action']
+          true
+        else false
+        end
+        if create_form \
+        and @fnb \
+        and @fnb=~/\S+/
+          %{
+ 
+
+ }
+        elsif create_form
+          %{
+ 
+
+ }
+        else ''
+        end
+      end
+      def search_action #check
+        if search?
+        else ''
+        end
+      end
+      self
+    end
+    def source_file_path
+      file=@fns.gsub(/\.ssm(?:\.sst)?/,'.ssm.sst')
+      unless file =~/\.ssm\.sst$/; "#{Dir.pwd}"
+      else "#{processing_path.composite_file}"
+      end
+    end
+    def source_file_with_path
+      file=@fns.gsub(/\.ssm(?:\.sst)?/,'.ssm.sst')
+      "#{source_file_path}/#{file}"
+    end
+    def texpdf_hyperlinks(cli)
+      @cli=cli
+      @hyplnks=if cli != :na
+        cli
+      elsif (defined? @rc['default']['pdf_hyperlinks']) \
+      && (@rc['default']['pdf_hyperlinks']=~/color/)
+        :color
+      elsif (defined? @rc['default']['pdf_hyperlinks']) \
+      && (@rc['default']['pdf_hyperlinks'] \
+      =~/(?:no-color|color-off|mono(?:chrome)?)/)
+        :mono
+      else :na
+      end
+      def landscape
+        if @cli != :na
+          @cli
+        elsif (defined? @rc['default']['pdf_hyperlinks_landscape']) \
+        && (@rc['default']['pdf_hyperlinks_landscape']=~/color/)
+          :color
+        elsif (defined? @rc['default']['pdf_hyperlinks_landscape']) \
+        && (@rc['default']['pdf_hyperlinks_landscape'] \
+        =~/(?:no-color|color-off|mono(?:chrome)?)/)
+          :mono
+        elsif @hyplnks != :na
+          @hyplnks
+        else :na
+        end
+      end
+      def portrait
+        if @cli != :na
+          @cli
+        elsif (defined? @rc['default']['pdf_hyperlinks_portrait']) \
+        && (@rc['default']['pdf_hyperlinks_portrait']=~/color/)
+          :color
+        elsif (defined? @rc['default']['pdf_hyperlinks_portrait']) \
+        && (@rc['default']['pdf_hyperlinks_portrait'] \
+        =~/(?:no-color|color-off|mono(?:chrome)?)/)
+          :mono
+        elsif @hyplnks != :na
+          @hyprlnks
+        else :na
+        end
+      end
+      self
+    end
+    def font
+      def size(pt=nil)
+        if pt && pt != :na
+          pt
+        elsif defined? @rc['default']['fontsize'] \
+        && @rc['default']['fontsize']=~/\d{1,2}/
+          @rc['default']['fontsize']
+        else :na
+        end
+      end
+      def texpdf
+        # you may wish to check selected font against available fonts:
+        # fc-list :outline -f "%{family}\n"
+        # fc-list :lang=ja
+        def main
+          (defined? @rc['default']['texpdf_fontface']) \
+          && (@rc['default']['texpdf_fontface']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface']
+          : 'Liberation Sans'
+        end
+        def sans                       # not used
+          (defined? @rc['default']['texpdf_fontface_sans']) \
+          && (@rc['default']['texpdf_fontface_sans']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_sans']
+          : 'Liberation Sans'
+        end
+        def serif                      # not used
+          (defined? @rc['default']['texpdf_fontface_serif']) \
+          && (@rc['default']['texpdf_font_serif']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_serif']
+          : 'Liberation Serif'
+        end
+        def mono
+          (defined? @rc['default']['texpdf_fontface_mono']) \
+          && (@rc['default']['texpdf_fontface_mono']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_mono']
+          : 'Liberation Mono'
+        end
+        def cjk
+          (defined? @rc['default']['texpdf_fontface_cjk']) \
+          && (@rc['default']['texpdf_fontface_cjk']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_cjk']
+          : 'IPAGothic' # 'IPAGothic' # 'IPAMincho' # 'TakaoMincho' # 'VL Gothic'
+        end
+        def cjk_zh
+          (defined? @rc['default']['texpdf_fontface_cjk_zh']) \
+          && (@rc['default']['texpdf_fontface_cjk_zh']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_cjk_zh']
+          : 'IPAGothic'
+        end
+        def cjk_ja
+          (defined? @rc['default']['texpdf_fontface_cjk_ja']) \
+          && (@rc['default']['texpdf_fontface_cjk_ja']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_cjk_ja']
+          : 'IPAGothic'
+        end
+        def cjk_ko
+          (defined? @rc['default']['texpdf_fontface_cjk_ko']) \
+          && (@rc['default']['texpdf_fontface_cjk_ko']=~/\S{3,}/)  \
+          ? @rc['default']['texpdf_fontface_cjk_ko']
+          : 'IPAGothic'
+        end
+        def size(pt=nil)
+          if pt && pt != :na
+            pt
+          elsif (defined? @rc['default']['texpdf_fontsize']) \
+          && (@rc['default']['texpdf_fontsize']=~/\d{1,2}/)
+            @rc['default']['texpdf_fontsize']
+          elsif (defined? @rc['default']['fontsize']) \
+          && (@rc['default']['fontsize']=~/\d{1,2}/)
+            @rc['default']['fontsize']
+          else
+            :na
+          end
+        end
+        self
+      end
+      self
+    end
+    def path_rel_links
+      def html_scroll_2
+        if @env.output_dir_structure.by_language_code?
+          '../../'
+        elsif @env.output_dir_structure.by_filetype?
+          '../'
+        else
+          '../'
+        end
+      end
+      def html_seg_2
+        if @env.output_dir_structure.by_language_code?
+          '../../../'
+        elsif @env.output_dir_structure.by_filetype?
+          '../../'
+        else
+          '../'
+        end
+      end
+      def html_scroll_1
+        if @env.output_dir_structure.by_language_code?
+          '../'
+        elsif @env.output_dir_structure.by_filetype?
+          '../'
+        else
+          './'
+        end
+      end
+      def html_seg_1
+        if @env.output_dir_structure.by_language_code?
+          '../../'
+        elsif @env.output_dir_structure.by_filetype?
+          '../../'
+        else
+          './'
+        end
+      end
+      self
+    end
+    def read_source_file_array(fns)
+      (fns !~/\.ssm.sst$/) \
+      ? (IO.readlines(fns, mode: 'r:utf-8', cr_newline: true))
+      : (IO.readlines(
+           "#{processing_path.composite_file}/#{fns}",
+           mode: 'r:utf-8',
+           cr_newline: true
+        ))
+    end
+    def read_source_file(fns)
+      read_source_file_array(fns)
+    end
+    def read_source_file_string(fns)
+      (fns !~/\.ssm.sst$/) \
+      ? (IO.read(fns, mode: 'r:utf-8', cr_newline: true))
+      : (IO.read(
+           "#{processing_path.composite_file}/#{fns}",
+           mode: 'r:utf-8',
+           cr_newline: true
+        ))
+    end
+    def source_file_processing_array(fns)
+      read_source_file_string(fns).split(/\s*\n\s*\n/m)
+    end
+    def path                           #dir
+      def home
+        @sys.home
+      end
+      def sisurc_path
+        SiSU_Get_Init::GetInit.new.sisu_yaml.rc_path
+      end
+      def pwd
+        @sys.pwd
+      end
+      def stub_pwd
+        @stub_pwd
+      end
+      def base_markup_dir_stub
+        @base_markup_dir_stub
+      end
+      def stub_epub
+        @stub_epub
+      end
+      def stub_src
+        @stub_src
+      end
+      def stub_pod
+        @stub_pod
+      end
+      def etc
+        defaults[:sisu_etc]            #live/dynamic
+      end
+      def arch
+        @sys.dir_arch
+      end
+      def sitearch
+        @sys.dir_sitearch
+      end
+      def bin
+        @sys.dir_bin
+      end
+      def share                        #shared data repository source directory
+        #SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:green).
+        #  mark(defaults[:sisu_share])
+        defaults[:sisu_share]
+      end
+      def style
+        if @md \
+        && ((@md.opt.opt_act[:dump][:bool] \
+        &&   @md.opt.opt_act[:dump][:inst]) \
+        ||  (@md.opt.opt_act[:redirect][:bool] \
+        &&   @md.opt.opt_act[:redirect][:inst]))
+          'css'
+        else
+         defaults[:stylesheet_stub]
+        end
+      end
+      def sample_data                  #sample data repository source directory
+        defaults[:sample_data_path]
+      end
+      def rc
+        @init.rc_path
+      end
+      def yamlrc
+        GetInit.new.sisu_yaml.rc_path
+      end
+      def man #check use
+        (defined? @rc['webserv']['man']) \
+        ? "#{webserv}/#{@rc['webserv']['man']}"
+        : defaults[:webserv_man]
+      end
+      def webserv_path #testing, check need, remove
+        webserv
+      end
+      def webserv                      #separation required for webrick which cannot use path.output (different requirements as no file is passed)
+        man_path=if @@man_path.nil?
+          man_path=if defined? @rc['webserv']['path'] \
+          and @rc['webserv']['path'] =~/\S\S+/
+            pwd=Dir.pwd
+            Dir.chdir(SiSU_Utils::Path.new.base_markup)
+            man_path=@@man_path=File.expand_path(@rc['webserv']['path'])
+            Dir.chdir(pwd)
+            man_path
+          else defaults[:webserv_path]
+          end
+        else @@man_path
+        end
+        man_path_head=man_path.gsub(/(\S+)\/[^\/\s]+$/,'\1')
+        unless FileTest.directory?(man_path)
+          FileUtils::mkdir_p(man_path) if File.writable?("#{man_path_head}/.")
+        end
+        @webserv_path=if defined? man_path \
+        and File.writable?("#{man_path}/.")
+          man_path #web server path as configured in rc file
+        elsif FileTest.directory?(defaults[:webserv_path]) \
+        and File.writable?("#{defaults[:webserv_path]}/.") #web server path default
+          defaults[:webserv_path]
+        else #create default directory under home and place output there
+          unless FileTest.directory?(defaults[:output_local])
+            FileUtils::mkdir_p(defaults[:output_local])
+          end
+          defaults[:output_local]
+        end
+      end
+      def webserv_stub_ensure
+        FileUtils::mkdir_p(path.webserv) unless FileTest.directory?(path.webserv)
+        FileUtils::mkdir_p("#{path.webserv}/#{@base_markup_dir_stub}") \
+          unless FileTest.directory?("#{path.webserv}/#{@base_markup_dir_stub}")
+      end
+      def webserv_map_pwd #dir
+        "#{path.webserv}/#{base_markup_dir_stub}"
+      end
+      def webserv_dir                  #fixed/hard path to /www web/presentation directory, on Debian /var/www subdirectories are created within it, depending on markup directory stub-name (last segment of markup directory name)
+        defaults[:webserv_dir]
+      end
+      def webserv_image                #web/presentation directory, subdirectories are created within it, depending on markup directory stub-name (last segment of markup directory name)
+        images=if defined? @rc['webserv']['images']
+          @rc['webserv']['images']
+        else defaults[:images]
+        end
+        "#{path.webserv}/#{images}"
+      end
+      def output                       #web/webserv output directory... subdirectory into which further subdirectories are made based on file names
+        r=Px[:lng_lst_rgx]
+        u=/.+?\/([^\/]+)(?:\/(?:#{r})$|$)/
+        base_stub=@sys.pwd.gsub(u,'\1')
+        if Dir.pwd =~/\/#{Gt[:sisupod]}\/[^\/]+\/#{Gt[:pod]}\/#{Gt[:doc]}/
+          "#{path.webserv}/#{Gt[:doc]}"
+        else
+          "#{path.webserv}/#{base_stub}"
+        end
+      end
+      def feed
+        (defined? @rc['webserv']['feed']) \
+        ? ("#{public_output}/#{@rc['webserv']['feed']}")
+        : (defaults[:webserv_feed])
+      end
+      def feed_home
+        "#{public_output}/#{@rc['webserv']['feed_home']}"
+      end
+      def scripts                      #used previously only to include tla version info
+        if defined? @rc['project']['path']
+          "#{home}/#{@rc['project']['path']}"
+        end
+      end
+      def cgi
+        (defined? @rc['webserv']['cgi']) \
+        ? "#{@rc['webserv']['cgi']}"
+        : (defaults[:webserv_cgi])
+      end
+      def php
+        (defined? @rc['webserv']['php']) \
+        ? "#{public_output}/#{@rc['webserv']['php']}"
+        : (defaults[:webserv_php])
+      end
+      #% programs
+      def output_tell
+        url.webserv_map_pwd
+      end
+      def image_source_sisu_includes(md=nil)
+        if md \
+        and (md.opt.sisu_install_type? == \
+        :full_path_to_sisu_bin_in_sisu_dir_tree) \
+        and FileTest.directory?(
+          "#{md.opt.sisu_data_dir?}/image"
+        )==true
+          "#{md.opt.sisu_data_dir?}/image"
+        else
+          "#{share}/image"
+        end
+      end
+      def image_source(md=nil)                 #image repository source directory
+        if defined? @rc['image']['path'] \
+        and defined? @rc['image']['public']
+          pth="#{@rc['image']['path']}"
+          "#{pth}/#{@rc['image']['public']}"
+        else
+          image_source_sisu_includes(md)
+        end
+      end
+      def image_source_include(md=nil)         #image repository source directory
+        if defined? @rc['image']['path'] \
+        and defined? @rc['image']['public'] \
+        and FileTest.directory?(
+          "#{@rc['image']['path']}/#{@rc['image']['public']}"
+        )==true
+          "#{@rc['image']['path']}/#{@rc['image']['public']}"
+        elsif FileTest.directory?("#{@@pwd}/#{defaults[:image_stub]}")==true
+          "#{@@pwd}/#{defaults[:image_stub]}"
+        elsif FileTest.directory?(
+          "#{SiSU_Utils::Path.new.base_markup}/#{defaults[:image_stub]}"
+        )==true
+          "#{SiSU_Utils::Path.new.base_markup}/#{defaults[:image_stub]}"
+        else
+          image_source_sisu_includes(md)
+        end
+      end
+      def image_external
+        "#{processing}/external_document/image"
+      end
+      def image_source_include_local
+        if FileTest.directory?(defaults[:image_local])
+          defaults[:image_local]
+        end
+      end
+      def image_source_include_remote
+        if FileTest.directory?(image_external)
+          image_external
+        end
+      end
+      self
+    end
+    def processing_path
+      def encoding
+        pth="#{processing}/#{defaults[:processing_encoding]}"
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def processing_base_tmp
+        defaults[:processing_path_tmp_base]
+      end
+      def tmp_root_dir
+        defaults[:processing_dir_tmp_root]
+      end
+      def root_dir
+        proposed_path_base=if defined? @rc['processing']['path'] \
+        and not @rc['processing']['path'].nil? \
+        and not @rc['processing']['path'].empty?
+          x=if @rc['processing']['path'] =~/^(?:~|home)$/
+            home #fix
+          else @rc['processing']['path']
+          end
+        else nil
+        end
+        proposed_dir=if defined? @rc['processing']['dir'] \
+        and not @rc['processing']['dir'].nil? \
+        and not @rc['processing']['dir'].empty?
+          @rc['processing']['dir']
+        else defaults[:processing_dir]
+        end
+        v=SiSU_Env::InfoVersion.instance.get_version
+        v_dev=(DEVELOPER[:maintenance]==:true) \
+        ? "_#{v.version}"
+        : ''
+        path=if proposed_path_base \
+        and FileTest.directory?(proposed_path_base) \
+        and File.writable?("#{proposed_path_base}/.")
+          x=proposed_dir \
+          ? "#{proposed_path_base}/#{proposed_dir}"
+          : "#{proposed_path_base}/#{defaults[:processing_dir]}"
+        else defaults[:processing_dir_tmp_root]
+        end
+        path = path + v_dev
+      end
+      def usr_dir?
+        case root_dir
+        when /^\/home/ then false
+        else                true
+        end
+      end
+      def stub_dir
+        (usr_dir?) \
+        ? ("#{root_dir}/#{user}/#{stub_pwd}")
+        : ("#{root_dir}/#{stub_pwd}") # see defaults[:processing_path]
+      end
+      def stub_dir_orig # ends up with lang, if lang dir
+        (usr_dir?) \
+        ? ("#{root_dir}/#{user}/#{stub_pwd}")
+        : ("#{root_dir}/#{stub_pwd}") # see defaults[:processing_path]
+      end
+      def processing_sisupod(opt=nil)  #processing directory, used/needed for sisu work files, has sub-directories (ao,tex etc)
+        @opt=opt
+        def paths
+          processing_path_usr="#{root_dir}/#{user}"
+          processing_path_fnb=processing_path_usr \
+            + '/' + Gt[:pods] \
+            + '/' + @opt.fng
+          processing_path_sisupod=processing_path_fnb \
+            + '/' + Gt[:sisupod]
+          {
+            fnb: processing_path_fnb,
+            sisupod: processing_path_sisupod,
+          }
+        end
+        def make
+          unless FileTest.directory?(root_dir)
+            FileUtils::mkdir_p(root_dir)
+            File.chmod(0777,root_dir)
+          end
+          if usr_dir?
+            processing_path_usr="#{root_dir}/#{user}"
+            FileUtils::mkdir_p(processing_path_usr) \
+              unless FileTest.directory?(processing_path_usr)
+            File.chmod(0700,processing_path_usr)
+          end
+          sisupod_processing_path=paths[:sisupod]
+          FileUtils::mkdir_p(sisupod_processing_path) \
+            unless FileTest.directory?(sisupod_processing_path)
+          sisupod_processing_path_lng=if defined? @opt.lng
+            sisupod_processing_path \
+              + '/' + Gt[:doc] \
+              + '/' + @opt.lng
+          else
+            sisupod_processing_path \
+              + '/' + Gt[:doc]
+          end
+          unless FileTest.directory?(sisupod_processing_path_lng)
+            #puts "a processing directory (#{sisupod_processing_path_lng}) is being created for use by sisu"
+            FileUtils::mkdir_p(sisupod_processing_path_lng)
+            File.chmod(0700,sisupod_processing_path_lng)
+          end
+          sisupod_processing_path
+        end
+        self
+      end
+      def processing                   #processing directory, used/needed for sisu work files, has sub-directories (ao,tex etc)
+        unless FileTest.directory?(root_dir)
+          FileUtils::mkdir_p(root_dir)
+          File.chmod(0777,root_dir)
+        end
+        if usr_dir?
+          processing_path_usr="#{root_dir}/#{user}"
+          FileUtils::mkdir_p(processing_path_usr) \
+            unless FileTest.directory?(processing_path_usr)
+          File.chmod(0700,processing_path_usr)
+        end
+        FileUtils::mkdir_p(stub_dir) \
+          unless FileTest.directory?(stub_dir)
+        File.chmod(0700,stub_dir)
+        path_processing=[
+          stub_dir,
+          defaults[:processing_path],
+          defaults[:processing_path_home]
+        ]
+        processing=nil
+        path_processing.each do |v|                                              #
+          processing=v
+          unless FileTest.directory?(processing)
+            FileUtils::mkdir_p(processing)
+            File.chmod(0700,processing)
+          end
+          break
+        end
+        processing
+      end
+      def ao
+        pth=if defined? @rc['processing']['dal'] \
+          and @rc['processing']['dal'].is_a?(String)
+          "#{processing}/#{@rc['processing']['dal']}"
+        else "#{processing}/#{defaults[:processing_ao]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def tune
+        pth=if defined? @rc['processing']['tune'] \
+          and @rc['processing']['tune'].is_a?(String)
+          "#{processing}/#{@rc['processing']['tune']}"
+        else "#{processing}/#{defaults[:processing_tune]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def composite_file
+        pth=processing_path.ao  #"#{processing}/composite"
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def git
+        pth=if defined? @rc['git']['dir'] \
+        and @rc['git']['dir'].is_a?(String)
+          (@rc['git']['dir'] =~/^(?:~|home)$/) \
+          ? home + '/' + Gt[:git]
+          : @rc['git']['dir'] + '/' + Gt[:git]
+        else defaults[:processing_git]
+        end
+        unless FileTest.directory?(pth)
+          FileUtils::mkdir_p(pth)
+          File.chmod(0700,pth)
+        end
+        pth
+      end
+      def odf_pth
+        pth="#{processing}/odf/#{@fns}"
+        pth
+      end
+      def odf
+        odt
+      end
+      def odt
+        pth=odf_pth + '/odt'
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def odf
+        pth="#{processing}/odf"
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def odt_bld
+        FileUtils::rm_rf(processing_path.odt)
+        FileUtils::mkdir_p(processing_path.odt) \
+          unless FileTest.directory?(processing_path.odt)
+        FileUtils::mkdir_p("#{processing_path.odt}/Configurations2") \
+          unless FileTest.directory?("#{processing_path.odt}/Configurations2")
+        FileUtils::mkdir_p("#{processing_path.odt}/META-INF") \
+          unless FileTest.directory?("#{processing_path.odt}/META-INF")
+        FileUtils::mkdir_p("#{processing_path.odt}/Pictures") \
+          unless FileTest.directory?("#{processing_path.odt}/Pictures")
+        FileUtils::mkdir_p("#{processing_path.odt}/Thumbnails") \
+          unless FileTest.directory?("#{processing_path.odt}/Thumbnails")
+        processing_path.odt
+      end
+      def epub
+        "#{processing}/epub/#{@fnb}"
+      end
+      def epub_bld #(md)
+        FileUtils::rm_rf(processing_path.epub) \
+          if FileTest.directory?(processing_path.epub)
+        FileUtils::mkdir_p(processing_path.epub) \
+          unless FileTest.directory?(processing_path.epub)
+        FileUtils::mkdir_p("#{processing_path.epub}/META-INF") \
+          unless FileTest.directory?("#{processing_path.epub}/META-INF")
+        FileUtils::mkdir_p("#{processing_path.epub}/#{Ep[:d_oebps]}/image") \
+          unless FileTest.directory?("#{processing_path.epub}/#{Ep[:d_oebps]}/image")
+        FileUtils::mkdir_p("#{processing_path.epub}/#{Ep[:d_oebps]}/css") \
+          unless FileTest.directory?("#{processing_path.epub}/#{Ep[:d_oebps]}/css")
+        processing_path.epub
+      end
+      def epub_cp_images(md)
+        pth="#{processing_path.epub}/#{Ep[:d_oebps]}/image"
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        src=(md.opt.sisu_install_type? == :full_path_to_sisu_bin_in_sisu_dir_tree) \
+        ? "#{md.opt.sisu_data_dir?}/image"
+        : "#{md.opt.sisu_data_dir?}/sisu/image"
+        images=%W[bullet_09.png arrow_next_red.png arrow_prev_red.png arrow_up_red.png]
+        images.each do |i| #move to avoid repeated tests
+          if FileTest.file?("#{src}/#{i}")
+            FileUtils::cp("#{src}/#{i}","#{pth}/#{i}") \
+              unless FileTest.file?("#{pth}/#{i}")
+          else STDERR.puts %{\t*WARN* did not find image - "#{i}" [#{__FILE__}:#{__LINE__}]}
+          end
+        end
+        pth
+      end
+      def tex
+        pth=if defined? @rc['processing']['latex'] \
+        and @rc['processing']['latex'].is_a?(String)
+          "#{processing}/#{@rc['processing']['latex']}"
+        else "#{processing}/#{defaults[:processing_latex]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def texi
+        pth=if defined? @rc['processing']['texinfo'] \
+        and @rc['processing']['texinfo'].is_a?(String)
+          "#{processing}/#{@rc['processing']['texinfo']}"
+        else "#{processing}/#{defaults[:processing_texinfo]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def texinfo                      #texinfo webserv, check
+        "#{processing}/#{defaults[:processing_texinfo]}"
+      end
+      def manpage
+        "#{path.output}/man"
+      end
+      def lout
+        pth=if defined? @rc['processing']['lout'] \
+        and @rc['processing']['lout'].is_a?(String)
+          "#{processing}/#{@rc['processing']['lout']}"
+        else "#{processing}/#{defaults[:processing_lout]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def sql
+        pth="#{processing}/sql"
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def sqlite
+        pth=if defined? @rc['processing']['sqlite'] \
+        and @rc['processing']['sqlite'].is_a?(String)
+          "#{processing}/#{@rc['processing']['sqlite']}"
+        else "#{processing}/#{defaults[:processing_sqlite]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      def postgresql
+        pth=if defined? @rc['processing']['postgresql'] \
+        and @rc['processing']['postgresql'].is_a?(String)
+          "#{processing}/#{@rc['processing']['postgresql']}"
+        else "#{processing}/#{defaults[:processing_postgresql]}"
+        end
+        FileUtils::mkdir_p(pth) unless FileTest.directory?(pth)
+        pth
+      end
+      self
+    end
+    def url
+      def hostname
+        "http://#{@sys.hostname}"
+      end
+      def dir_url
+        "file://#{path.webserv}/#{stub_pwd}"
+      end
+      def localhost
+        "http://localhost/#{stub_pwd}"
+      end
+      def local
+        "http://#{hostname}/#{@stub_pwd}"
+      end
+      def root
+        if defined? @rc['webserv']['url_root'] \
+        and @rc['webserv']['url_root'] =~/https?:\/\//
+          "#{@rc['webserv']['url_root']}/#{@stub_pwd}"
+        elsif defined? @rc['webserv']['url_root'] \
+        and @rc['webserv']['url_root'] =~/localhost/
+          "http://localhost/#{@stub_pwd}"
+        else "file://#{path.output}"
+        end
+      end
+      def remote
+        root
+      end
+      def txt
+        "#{root}/txt"
+      end
+      def html
+        "#{root}/html"
+      end
+      def epub
+        "#{root}/epub"
+      end
+      def odt
+        "#{root}/odt"
+      end
+      def pdf
+        "#{root}/pdf"
+      end
+      def src_txt
+        "#{root}/src"
+      end
+      def src_pod
+        "#{root}/pod"
+      end
+      def pot
+        "#{root}/po4a/pot"
+      end
+      def po
+        "#{root}/po4a/po"
+      end
+      def webserv_host_base(opt=nil)
+        if defined? @rc['webserv']['host']
+          case  @rc['webserv']['host']
+          when /https?:\/\// then @rc['webserv']['host']
+          when /\S+/         then "http://#{@rc['webserv']['host']}"
+          else                    defaults[:webserv_host_cgi]
+          end
+        else                      defaults[:webserv_host_cgi]
+        end
+      end
+      def webserv_cgi(opt=nil)         #web url for local webserv (localhost, or hostname)
+        http=if defined? @rc['webserv_cgi']['host'] \
+        and @rc['webserv_cgi']['host'].is_a?(String)
+          http=((@rc['webserv_cgi']['host'] =~ /https?:\/\//) ? '' : 'http://') #check https? missing
+          if port.webserv_port_cgi
+            http + @rc['webserv_cgi']['host'] + ':' \
+            + port.webserv_port_cgi + '/' \
+            + @stub_pwd
+          else
+            http + @rc['webserv_cgi']['host'] + '/' \
+            + @stub_pwd
+          end
+        else
+          http=((webserv_host_base=~/https?:\/\//) ? '' : 'http://')
+          if port.webserv_port_cgi(opt)
+            http + webserv_host_base + ':' \
+            + port.webserv_port_cgi(opt) + '/'\
+            + @stub_pwd
+          else
+            http + webserv_host_base + '/' \
+            + @stub_pwd
+          end
+        end
+        http=http.strip
+      end
+      def webserv_base_cgi(opt=nil)    #web url for local webserv (localhost, or hostname)
+        http_cgi=if opt.selections.str =~/--webserv-(?:cgi|db|search)[=-]["']?(\S+)["']+/
+          m=$1
+          (m=~/http\/\/:/) ? m : %{http://#{m}}
+        elsif defined? @rc['webserv_cgi']['host'] \
+        and @rc['webserv_cgi']['host'].is_a?(String)
+          http=((@rc['webserv_cgi']['host'] =~ /https?:\/\//) ? '' : 'http://')
+          if port.webserv_port_cgi(opt)
+            http + @rc['webserv_cgi']['host'] + ':' \
+            + port.webserv_port_cgi(opt).to_s
+          else
+            http + @rc['webserv_cgi']['host']
+          end
+        else
+          http=((webserv_host_base=~/https?:\/\//) ? '' : 'http://')
+          if port.webserv_port_cgi(opt)
+            http + webserv_host_base + ':' \
+            + port.webserv_port_cgi(opt).to_s
+          else http + webserv_host_base
+          end
+        end
+        http_cgi=http_cgi.strip
+        #%q{http://#{ENV['HTTP_HOST']}}
+      end
+      def webrick #must have a port    #REMOVE
+        if defined? @rc['webserv_cgi']['host'] \
+        and @rc['webserv_cgi']['host'].is_a?(String)
+          http=if @rc['webserv_cgi']['host'] =~/http:\/\//
+            'http://'
+          elsif @rc['webserv_cgi']['host'] =~/https:\/\//
+            'https://'
+          else defaults
+          end
+          http + @rc['webserv_cgi']['host']
+        elsif webserv_host_base \
+        and webserv_host_base.is_a?(String)
+          webserv_host_base
+        else
+          #http + 'localhost'
+          'localhost'
+        end
+      end
+      def webserv                      #web url for local webserv (localhost, or hostname)
+        if defined? @rc['webserv']['url_root'] \
+        and @rc['webserv']['url_root'] =~/http/
+          # needed for alternative output dir structures, fixes manifest url links, check may cause problems elsewhere
+          @rc['webserv']['url_root']
+        elsif path.webserv_dir \
+        and path.webserv =~ /#{path.webserv_dir}/ #revisit
+          path.webserv + '/' \
+            + @base_markup_dir_stub.
+              gsub(/#{path.webserv_dir}/,
+                "#{url.hostname}/#{@stub_pwd}")
+        elsif defined? @rc['webserv']['webrick_url'] \
+        and @rc['webserv']['webrick_url']==false
+          'file://' + path.webserv
+        elsif port.webserv_port_cgi =~/\S+/
+          url.hostname + ':' + port.webserv_port_cgi
+        else
+          url.hostname
+        end
+      end
+      def webserv_base                 #web url for local webserv (localhost, or hostname)
+        if path.webserv_dir \
+        and path.webserv =~ /#{path.webserv_dir}/ #revisit
+          path.webserv + '/' \
+          + @stub_pwd.
+            gsub(/#{path.webserv_dir}/,
+              "#{url.hostname}")
+        elsif defined? @rc['webserv']['webrick_url'] \
+        and @rc['webserv']['webrick_url']==false
+          "file://#{path.webserv}"
+        else "#{url.webrick_base}"
+        end
+      end
+      def webserv_files_from_db(opt=nil) #sort this out, messy
+        if opt.selections.str =~/--webserv-output[=-]["']?(\S+)["']+/
+          m=$1
+          (m=~/(?:http|file\/)\/\/:/) ? m : %{http://#{m}}
+        else
+          show_output_on=if defined? @rc['webserv_cgi']['show_output_on']
+            @rc['webserv_cgi']['show_output_on']
+          elsif  defined? @rc['webserv_cgi']['file_links']
+            @rc['webserv_cgi']['file_links']
+          else ''
+          end
+          m=case show_output_on
+          when /webserv_cgi/ then url.webserv_base_cgi(opt)
+          when /webserv/     then @rc['webserv']['url_root']
+          when /https?:\/\// then @rc['webserv_cgi']['file_links']
+          when /\S+/         then 'http://' + @rc['webserv_cgi']['file_links']
+          else                     webserv_base_cgi(opt)
+          end
+        end
+        #%q{http://#{ENV['HTTP_HOST']}/cgi-bin}
+      end
+      def cgi_sample_search_form_name(opt=nil)
+        if opt.selections.str \
+        =~/--(?:cgi-)?search-form-name[=-]["']?(\S+?\.cgi)/
+          $1
+        elsif not opt.selections.str =~/--db[=-]["']?sqlite/ \
+        and defined? @rc['search'] \
+        and defined? @rc['search']['sisu'] \
+        and defined? @rc['search']['sisu']['action'] \
+        and @rc['search']['sisu']['action'] =~/https?:\/\/\S+?\.cgi/
+          /(?:https?:\/\/\S+?)\/([^\/]+?\.cgi)$/.
+            match(@rc['search']['sisu']['action'])[1]
+        else
+          (opt.selections.str =~/--db[=-]["']?sqlite/) \
+          ? "#{Db[:name_prefix_db]}sqlite.cgi" \
+          :  "#{Db[:name_prefix_db]}pg.cgi"
+        end
+      end
+      def sample_search_form_title(organised_by=:language)
+        title=if defined? @rc['search']['sisu']['title'] \
+        and @rc['search']['sisu']['title'] =~/\S+/
+          @rc['search']['sisu']['title']
+        else %{SiSU (generated sample) search form}
+        end
+        title=title + " (content organised by #{organised_by})"
+      end
+      def output_tell                  #BROKEN Revisit 2011-02
+        output_type=if defined? @rc['show_output_on'] \
+        and @rc['show_output_on'] \
+        =~/^(?:filesystem|webserv|(?:local|remote)(?:_webserv)?|webrick)/
+          @rc['show_output_on']
+        else 'filesystem'
+        end
+        case output_type
+        when /^filesystem(?:_url)?/       then url.dir_url
+        when /^remote(?:_webserv)?/       then url.remote
+        when /^(?:webserv|local_webserv)/ then url.local
+        when /^local(:\d+)/               then url.hostname + $1 + '/' + stub_pwd
+        when /^localhost(:\d+)/           then url.localhost + $1 +  '/' + stub_pwd
+        when /^localhost/                 then url.localhost
+        when /^webrick/                   then url.webrick
+        when /^path/                      then url.webserv_map_pwd
+        else                                   url.webserv_map_pwd
+        end
+      end
+      def images
+        "#{Xx[:html_relative2]}/_sisu/image"
+      end
+      #def images
+      #  '../_sisu/image'
+      #end
+      def images_local
+        if FileTest.directory?(path.image_source_include)
+          path.image_source_include
+        else
+          if @@local_image==true
+            cmd=@md.opt.selections.str ? @md.opt.selections.str : ''
+            SiSU_Screen::Ansi.new(
+              cmd,
+              "WARNING - no local image directory or images:",
+              defaults[:image_local]
+            ).warn unless @md.opt.act[:quiet][:set]==:on
+            @@local_image=false
+          end
+          url.images
+        end
+      end
+      def images_external
+        if FileTest.directory?(image_external)
+          if @@image_flag
+            images=Dir.glob("#{image_external}/*.{png,jpg,gif}")
+            pth=path.webserv + '/' \
+            + @stub_pwd
+            FileUtils::mkdir_p("#{pth}/_sisu/image_external") \
+              unless FileTest.directory?("#{pth}/_sisu/image_external")
+            images.each { |i| File.install(i,"#{pth}/#{i}") } \
+              unless images.length > 0
+            @@image_flag=false
+          end
+          "#{Xx[:html_relative2]}/_sisu/image_external"
+        else
+          if @@local_image==true
+            SiSU_Screen::Ansi.new(
+              @cmd,
+              'WARNING - image directory for external images or no such images:',
+              :image_external
+            ).warn unless @md.opt.act[:quiet][:set]==:on
+            @@local_image=false
+          end
+          url.images_external
+        end
+      end
+      def images_epub
+        './image'
+      end
+      self
+    end
+    def port
+      def webrick_port
+        if @md \
+        and @md.opt.act[:sample_search_form][:set]==:on \
+        and @md.opt.selections.str=~/port=(\d+)/
+           $1
+        else
+          if defined? @rc['webserv_cgi']['port']
+            if @rc['webserv_cgi']['port'].nil? \
+            and (defined? @md.opt.selections \
+            and @md.opt.selections.str=~/webrick/)
+              defaults[:webserv_port_cgi]
+            elsif not @rc['webserv_cgi']['port'].nil?
+              @rc['webserv_cgi']['port']
+            else defaults[:webserv_port_cgi]
+            end
+          else   defaults[:webserv_port_cgi]
+          end
+        end
+      end
+      def webserv_port_cgi(opt=nil)
+        port=if opt \
+        and opt.act[:sample_search_form][:set]==:on \
+        and opt.selections.str=~/port[=-](\d+)/
+           $1
+        else
+          port=if defined? @rc['webserv_cgi']['port']
+            if @rc['webserv_cgi']['port'].nil? \
+            and (defined? opt.selections \
+            and opt.selections.str=~/webrick/)
+              defaults[:webserv_port_cgi]
+            elsif not @rc['webserv_cgi']['port'].nil?
+              @rc['webserv_cgi']['port']
+            else nil
+            end
+          else
+            if (defined? opt.selections \
+            and opt.selections.str=~/webrick/)
+              defaults[:webserv_port_cgi]
+            else nil
+            end
+          end
+        end
+        port.to_s
+      end
+      self
+    end
+    def digest_conf?
+      if defined? @rc['default']['digest'] \
+      and @rc['default']['digest'] != nil
+        case @rc['default']['digest']
+        when /^sha(?:5|512)?$/ then :sha512
+        when /^sha(?:2|256)?$/ then :sha256
+        when /^md5$/           then :md5
+        else                        :sha256
+        end
+      else                          :sha256
+      end
+    end
+    def digest(opt=nil)
+      @opt=opt
+      def type
+        if @opt
+          case @opt.act[:hash_digest_algo]
+          when :sha512 then :sha512
+          when :sha256 then :sha256
+          when :md5    then :md5
+          else              digest_conf?
+          end
+        else                digest_conf?
+        end
+      end
+      def length
+        case digest(@opt).type
+        when :sha512 then 128
+        when :sha256 then  64
+        when :md5    then  32
+        else               64
+        end
+      end
+      def pattern
+        "[0-9a-f]{#{digest(@opt).length}}" #/[0-9a-f]{#{digest.length}}/
+      end
+      self
+    end
+    def program
+      def text_editor
+        if defined? @rc['program_select']['editor'] \
+        and @rc['program_select']['editor'] =~/\S\S+/
+          @rc['program_select']['editor']
+        elsif defined? @rc['program_select']['text_editor'] \
+        and @rc['program_select']['text_editor'] =~/\S\S+/
+          @rc['program_select']['text_editor']
+        else 'editor'                                                            #'gvim -c :R -c :S'
+        end
+      end
+      def pdf_viewer
+        ((defined? @rc['program_select']['pdf_viewer']) \
+        && @rc['program_select']['pdf_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['pdf_viewer']
+        : 'pdf-viewer'                                                        #'evince'
+      end
+      def web_browser
+        if defined? @rc['program_select']['www_browser'] \
+        and @rc['program_select']['www_browser'] =~/\S\S+/
+          @rc['program_select']['www_browser']
+        elsif defined? @rc['program_select']['web_browser'] \
+        and @rc['program_select']['web_browser'] =~/\S\S+/
+          @rc['program_select']['web_browser']
+        else 'x-www-browser'                                                      #'firefox' 'iceweasel' 'kazehakase' 'galeon'
+        end
+      end
+      def www_browser
+        web_browser
+      end
+      def console_web_browser
+        if defined? @rc['program_select']['console_www_browser'] \
+        and @rc['program_select']['console_www_browser'] =~/\S\S+/
+          @rc['program_select']['console_www_browser']
+        elsif defined? @rc['program_select']['console_web_browser'] \
+        and @rc['program_select']['console_web_browser'] =~/\S\S+/
+          @rc['program_select']['console_web_browser']
+        else 'console-www-browser'                                             #'lynx' 'links' 'links2' 'elinks' 'w3m'
+        end
+      end
+      def console_www_browser
+        web_browser
+      end
+      def epub_viewer
+        ((defined? @rc['program_select']['epub_viewer']) \
+        && @rc['program_select']['epub_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['epub_viewer']
+        : 'ebook-viewer'                                                    #'calibre' 'fbreader'
+      end
+      def xml_viewer
+        ((defined? @rc['program_select']['xml_viewer']) \
+        && @rc['program_select']['xml_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['xml_viewer']
+        : text_editor
+      end
+      def docbook_viewer
+        ((defined? @rc['program_select']['xml_viewer']) \
+        && @rc['program_select']['xml_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['xml_viewer']
+        : text_editor
+      end
+      def fictionbook_viewer
+        ((defined? @rc['program_select']['xml_viewer']) \
+        && @rc['program_select']['xml_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['xml_viewer']
+        : text_editor
+      end
+      def xml_editor
+        xml_viewer
+      end
+      def odf_viewer
+        ((defined? @rc['program_select']['odf_viewer']) \
+        && @rc['program_select']['odf_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['odf_viewer']
+        : 'lowriter'                                                           #'odf-viewer','oowriter'
+      end
+      def manpage_viewer
+        'man'
+      end
+      def manpage_generator
+        ((defined? @rc['program_select']['man']) \
+        && @rc['program_select']['man'] =~/\S\S+/) \
+        ? @rc['program_select']['man']
+        : 'nroff -man'                                                        #'nroff -man' #'groff -man -Tascii'
+      end
+      def texinfo
+        ((defined? @rc['program_select']['info_viewer']) \
+        && @rc['program_select']['info_viewer'] =~/\S\S+/) \
+        ? @rc['program_select']['info_viewer']
+        : 'pinfo -f'                                                          #'pinfo -f' 'info' 'tkinfo'
+      end
+      def file_encoding
+        is=(defined? @rc['program_set']['file_encoding']) \
+        ? @rc['program_set']['encoding'] : ''
+        (is.nil? || is==true) ? 'encoding' : is
+      end
+      def wc #wordcount
+        is=(defined? @rc['program_set']['wc']) \
+          ? @rc['program_set']['wc'] : ''
+        (is.nil? || is==true) ? 'wc' : is
+      end
+      def tidy
+        is=(defined? @rc['program_set']['tidy']) \
+          ? @rc['program_set']['tidy'] : nil
+        (is.nil? || is==true) ? 'tidy' : is
+      end
+      def rmagick
+        is=(defined? @rc['program_set']['rmagick']) \
+          ? @rc['program_set']['rmagick'] : nil
+        (is.nil? || is==true) ? 'rmagick' : is
+      end
+      def rexml                        #should be part of ruby 1.8 but apparently not always
+        is=(defined? @rc['program_set']['rexml']) ? \
+          @rc['program_set']['rexml'] : ''
+        (is.nil? || is==true) ? 'rexml' : is
+      end
+      def pdflatex
+        is=(defined? @rc['program_set']['pdflatex']) ? \
+          @rc['program_set']['pdflatex'] : ''
+        (is.nil? || is==true) ? 'pdflatex' : is
+      end
+      def postgresql
+        is=(defined? @rc['program_set']['postgresql']) ? \
+          @rc['program_set']['postgresql'] : ''
+        (is.nil? || is==true) ? 'postgresql' : is
+      end
+      def sqlite
+        is=(defined? @rc['program_set']['sqlite']) ? \
+          @rc['program_set']['sqlite'] : ''
+        (is.nil? || is==true) ? 'sqlite' : is
+      end
+      self
+    end
+    def i18n
+      def language                     # language settings
+        m=/.+\/\S+?\~(\S+)/
+        pwd=Dir.pwd
+        conf=(defined? @rc['default']['language']) \
+        ? @rc['default']['language'] : nil
+        l=if pwd=~ m    then pwd[m,1]                                        #2 directory: by visible directory name
+        elsif conf      then @rc['default']['language']                      #3 config: from sisurc.yaml
+        else            defaults[:language]                                  #4 sisu: program default
+        end                                                                  #1 document: param gets
+        SiSU_Env::StandardiseLanguage.new(l)
+      end
+      #def multilingual
+      #  x=(defined? @rc['output_structure']['multilingual'] \
+      #  && @rc['output_structure']['multilingual'] ==true) \
+      #  ? true : false
+      #end
+      #def bundle
+      #  x=(defined? @rc['output_structure']['bundle'] \
+      #  && @rc['output_structure']['bundle'] ==true) \
+      #  ? true : false
+      #end
+      def lang_filename(l)
+        @lang={}
+        x=if output_dir_structure.by_language_code?
+          (( defined? @rc['default']['language_file']) \
+          && @rc['default']['language_file'] != nil) \
+          ? @rc['default']['language_file']
+          : 1
+        else 0
+        end
+        if (l != defaults[:language_code]) \
+        or (language.code != defaults[:language_code]) #watch
+          if x==1    then @lang[:pre],@lang[:mid],@lang[:post]="#{l}.",'',''
+          elsif x==2 then @lang[:pre],@lang[:mid],@lang[:post]='',".#{l}",''
+          elsif x==3 then @lang[:pre],@lang[:mid],@lang[:post]='','',".#{l}"
+          else            @lang[:pre],@lang[:mid],@lang[:post]='','',''
+          end
+        else              @lang[:pre],@lang[:mid],@lang[:post]='','',''
+        end
+        @lang
+      end
+      self
+    end
+    def file_encoding
+      is=''
+      if defined? @rc['program_set']['file_encoding']
+        is=@rc['program_set']['encoding']
+      end
+      if is.nil? \
+      or is==true
+        is='encoding'
+      end
+      is
+    end
+    def papersize                      # paper settings, default overidden in param if set within document
+      (defined? @rc['default']['papersize']) \
+      ? @rc['default']['papersize'].downcase
+      : (defaults[:papersize].downcase)
+    end
+    def sisupod_gen(fns_pod)
+      sisupod_gen_v3(fns_pod)
+    end
+    def sisupod_gen_v3(fns_pod)
+      pwd=Dir.pwd
+      sisupod_processing_path=
+        processing_path.processing + '/' + Gt[:sisupod]
+      if FileTest.directory?(sisupod_processing_path) \
+      or FileTest.file?(sisupod_processing_path)
+        FileUtils::rm_rf(sisupod_processing_path)
+      end
+      unless FileTest.directory?(sisupod_processing_path)
+        FileUtils::mkdir_p(sisupod_processing_path)
+      end
+      f_pod=if FileTest.file?("#{Dir.pwd}/#{fns_pod}")
+        "#{Dir.pwd}/#{fns_pod}"
+      elsif FileTest.file?(fns_pod)
+        fns_pod
+      end
+      if f_pod \
+      && FileTest.file?(f_pod)
+        (SiSU_Env::SystemCall.new.program_found?('tree')) \
+        ? 'tree ' + processing_path.processing + '/' + Gt[:sisupod]
+        : ''
+        if FileTest.directory?(processing_path.processing)
+          Dir.chdir(processing_path.processing)
+          system(%{tar xJf #{f_pod}})
+          Dir.chdir(pwd)
+        end
+        #system(tree)                                                          #enable if (/[vVM]/)
+      else
+        SiSU_Screen::Ansi.new(
+          '',
+          '*WARN* file not found: ' + fns_pod
+        ).warn unless @md.opt.act[:quiet][:set]==:on
+      end
+      sisupod_processing_path
+    end
+    def sisupod_gen_v2(fns_pod)
+      sisupod_processing_path=
+        processing_path.processing + '/' + Gt[:sisupod]
+      if FileTest.directory?(sisupod_processing_path) \
+      or FileTest.file?(sisupod_processing_path)
+        FileUtils::rm_rf(sisupod_processing_path)
+      end
+      unless FileTest.directory?(sisupod_processing_path)
+        FileUtils::mkdir_p(sisupod_processing_path)
+      end
+      (FileTest.file?(fns_pod)) \
+      ? system("unzip -q #{fns_pod} -d #{processing_path.processing}")
+      : (SiSU_Screen::Ansi.new(
+          '',
+          "*WARN* file not found: #{fns_pod}"
+        ).warn unless @md.opt.act[:quiet][:set]==:on)
+      sisupod_processing_path
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_info_port.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_info_port.rb"
+# <>
+module SiSU_Info_Port
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class InfoPort < SiSU_Info_Env::InfoEnv                  # se_info_env.rb
+    def initialize
+      @env=SiSU_Env::InfoEnv.new
+    end
+    def webrick
+      @env.port.webrick_port
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_info_system.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_info_system.rb"
+# <>
+module SiSU_Info_Sys_Gen
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class InfoSystemGen
+    begin
+      require 'rbconfig'
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('rbconfig NOT FOUND (LoadError)')
+    end
+    @@user,       @@home,     @@hostname,     @@pwd,     @@sisu_etc,                            @@host,                @@arch,                @@rbver,          @@dir_arch,               @@dir_sitearch,               @@dir_bin,               @@locale,                @@rc,@@sisurc_path,@@ad=
+      ENV['USER'],ENV['HOME'],ENV['HOSTNAME'],ENV['PWD'],RbConfig::CONFIG['sysconfdir'] + '/sisu',RbConfig::CONFIG['host'],RbConfig::CONFIG['arch'],%x{ruby -v}.strip,RbConfig::CONFIG['archdir'],RbConfig::CONFIG['sitearchdir'],RbConfig::CONFIG['bindir'],%x{locale charmap}.strip,nil, nil,          {} # %x{ruby -v}.strip # RbConfig::CONFIG['rb_ver']
+    out=RbConfig::CONFIG['localstatedir']
+    etc=RbConfig::CONFIG['sysconfdir'] + '/sisu'
+    share=RbConfig::CONFIG['datadir']  + '/sisu'
+    data=RbConfig::CONFIG['datadir']   + '/doc/sisu'
+    m=/.+\/(?:src\/)?(\S+)/m # m=/.+?\/(?:src\/)?([^\/]+)$/im # m=/.+\/(\S+)/m
+    @stub_pwd ||=@@pwd[m,1]
+    @base_markup_dir_stub=SiSU_Utils::Path.new.base_markup_stub
+    prcss_dir='_sisu_processing_'
+    prcss_dir_tmp_root="/tmp/#{prcss_dir}"
+    prcss_dir_stub="#{prcss_dir}/#{@stub_pwd}"
+    if @@user
+      tmp_processing="#{prcss_dir_tmp_root}/#{@@user}/#{@base_markup_dir_stub}"
+      tmp_processing_individual="#{prcss_dir_tmp_root}/#{@@user}/#{@base_markup_dir_stub}"
+    else #error
+      tmp_processing=tmp_processing_individual="/tmp/#{prcss_dir_stub}"
+    end
+    processing_pth=tmp_processing_individual
+    processing_dir=prcss_dir
+    processing_git="#{Dir.pwd}/#{Gt[:grotto]}"
+    #user=ENV['USER']
+    port_pgsql=if defined? ENV['PGPORT'] \
+    and not (ENV['PGPORT'].nil? \
+    || ENV['PGPORT'].empty?) \
+    and ENV['PGPORT']=~/^\d+$/
+      ENV['PGPORT']
+    else '5432'
+    end
+    IMAGES=:images
+    SISU_ETC=:sisu_etc
+    SISU_SHARE=:sisu_share
+    SAMPLE_DATA_PATH=:sample_data_path
+    IMAGE_STUB=:image_stub
+    STYLESHEET_STUB=:stylesheet_stub
+    IMAGE_LOCAL=:image_local
+    WEBSERV_PATH=:webserv_path
+    WEBSERV_MAN=:webserv_man
+    WEBSERV_PHP=:webserv_php
+    WEBSERV_CGI=:webserv_cgi
+    WEBSERV_RSS=:webserv_rss
+    WEBSERV_SQLITE=:webserv_sqlite
+    OUTPUT_LOCAL=:output_local
+    PROCESSING_DIR=:processing_dir
+    PROCESSING_PATH=:processing_path
+    PROCESSING_DIR_TMP_ROOT=:processing_dir_tmp_root
+    PROCESSING_PATH_TMP_BASE=:processing_path_tmp_base
+    PROCESSING_AO=:processing_ao
+    PROCESSING_TUNE=:processing_tune
+    PROCESSING_LATEX=:processing_latex
+    PROCESSING_TEXINFO=:processing_texinfo
+    PROCESSING_LOUT=:processing_lout
+    PROCESSING_SQLITE=:processing_sqlite
+    PROCESSING_POSTGRESQL=:processing_postgresql
+    PROCESSING_ENCODING=:processing_encoding
+    PROCESSING_GIT=:processing_git
+    PAPERSIZE=:papersize
+    #LANGUAGE=:language
+    #LANGUAGE_CODE=:language_code
+    MULTILINGUAL=:multilingual
+    BUNDLE=:bundle
+    CONCORD_MAX=:concord_max
+    DIGEST=:digest
+    WEBSERV_HOST_CGI=:webserv_host_cgi
+    WEBSERV_PORT_CGI=:webserv_port_cgi
+    POSTGRESQL_USER=:postgresql_user
+    POSTGRESQL_PORT=:postgresql_port
+    SQLITE_USER=:sqlite_user
+    SQLITE_PATH=:sqlite_path
+    SQLITE_PORT=:sqlite_port
+    DEFAULT_DIR={
+      IMAGES =>                   '_sisu/image',
+      SISU_ETC =>                 etc,
+      SISU_SHARE =>               share,
+      SAMPLE_DATA_PATH =>         data,
+      IMAGE_STUB =>               '_sisu/image',
+      STYLESHEET_STUB =>          '_sisu/css',
+      IMAGE_LOCAL =>              @@pwd + '/_sisu/image',
+      WEBSERV_PATH =>             out + '/www',
+      #WEBSERV_DIR =>             www, # uncomment for urls...
+      #WEBSERV_IMAGE =>            out + '/www/_sisu/image',
+      WEBSERV_MAN =>              out + '/www/man', #alter
+      WEBSERV_PHP =>              out + '/www/php',
+      WEBSERV_CGI =>              '/usr/lib/cgi-bin',
+      WEBSERV_RSS =>              out + '/www/feed',
+      WEBSERV_SQLITE =>           out + '/www/sqlite',
+      OUTPUT_LOCAL =>             @@home + '/sisu_www',
+      PROCESSING_DIR =>           processing_dir,
+      PROCESSING_PATH =>          processing_pth,
+      PROCESSING_DIR_TMP_ROOT  => prcss_dir_tmp_root,
+      PROCESSING_PATH_TMP_BASE => processing_pth,
+      PROCESSING_AO =>            'ao',
+      PROCESSING_TUNE =>          'tune',
+      PROCESSING_LATEX =>         'tex',
+      PROCESSING_TEXINFO =>       'texinfo',
+      PROCESSING_SQLITE =>        'sqlite',
+      PROCESSING_POSTGRESQL=>     'postgresql',
+      PROCESSING_ENCODING =>      'encoding',
+      PROCESSING_GIT =>           processing_git,
+      #TEXINFO_STUB =>             'texinfo',
+      PAPERSIZE =>                'A4', #A4, US_letter, book_b5, book_a5, US_legal
+      #LANGUAGE =>                 'English',
+      #LANGUAGE_CODE =>            'en', #change, unecessary duplication though currently used
+      MULTILINGUAL =>             false,
+      BUNDLE =>                   false,
+      CONCORD_MAX =>              260000,
+      DIGEST =>                   :sha256,
+      WEBSERV_HOST_CGI =>         'http://localhost',
+      WEBSERV_PORT_CGI =>         8081, #8111,8123,8081
+      POSTGRESQL_USER =>          @@user, #'ralph', # change user !!!
+      POSTGRESQL_PORT =>          port_pgsql,
+      #POSGRESQL_LINKS_PATH =>    '',
+      SQLITE_USER =>              @@user,
+      SQLITE_PATH =>              @@user, #??
+      SQLITE_PORT =>              '**',
+    }
+    @@default_dir=DEFAULT_DIR
+    m=/.+\/(?:src\/)?(\S+)/m # m=/.+?\/(?:src\/)?([^\/]+)$/im # m=/.+\/(\S+)/m
+    @@pwd=@pwd=SiSU_Utils::Path.new.base_markup
+    attr_accessor :user,:home,:hostname,:pwd,:host,:arch,:rbver,:dir_arch,:dir_sitearch,:dir_bin,:locale,:webserv_path,:webserv_host_cgi,:webserv_port_cgi,:default_dir,:rc_path,:ad_path
+    def initialize
+      @user,   @home, @hostname, @pwd, @sisu_etc, @host, @arch, @rbver, @dir_arch, @dir_sitearch, @dir_bin, @locale, @default_dir=
+        @@user,@@home,@@hostname,@@pwd,@@sisu_etc,@@host,@@arch,@@rbver,@@dir_arch,@@dir_sitearch,@@dir_bin,@@locale,@@default_dir
+      #note rbver is duplicated in InfoVersion
+    end
+  end
+end
+module SiSU_Info_Sys
+  class InfoSystem < SiSU_Info_Sys_Gen::InfoSystemGen
+    include Singleton
+    def initialize
+      super()
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_load.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_load.rb"
+# <>
+module SiSU_Load
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class Load
+    def initialize(prog,mandatory=false)
+      @prog,@mandatory=prog,mandatory
+    end
+    def prog
+      load_prog=false
+      $:.each do |reqpath|
+        if FileTest.exist?("#{reqpath}/#{@prog}.rb")
+          load_prog=true
+          #SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).ok("#{reqpath}/#{@prog}.rb loaded")
+          break
+        #else SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).warn("#{reqpath}/#{@prog}.rb not found")
+        end
+      end
+      if load_prog \
+      and @prog=~/dbi/
+        begin
+          require 'dbi'
+        rescue LoadError
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+            error('dbi NOT FOUND (LoadError)')
+        end
+      end
+      if load_prog
+        begin
+          require @prog
+        rescue LoadError
+          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+            error("#{@prog} NOT FOUND (LoadError)")
+        end
+      else
+        @mandatory \
+        ? (SiSU_Screen::Ansi.new(@prog,"*WARN* module required: #{@prog}").warn)
+        : '' #(SiSU_Screen::Ansi.new(@prog,"*WARN* #{@prog} load requested").warn)
+      end
+      load_prog
+    end
+    def prog?
+      load_prog=false
+      $:.each do |reqpath|
+        if FileTest.exist?("#{reqpath}/#{@prog}.rb"); load_prog=true
+          break
+        end
+      end
+      load_prog
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_processing.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_processing.rb"
+# <>
+module SiSU_Processing_Settings
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class ProcessingSettings
+    def initialize(md)
+      @md=md
+    end
+    def cnf_rc #sisurc.yml
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+    end
+    def env_rc #env rc (including sisurc.yml)
+      @env_rc ||=SiSU_Env::InfoEnv.new(@md.fns)
+    end
+    def doc_rc #document rc, make instructions
+      (defined? @md.make) \
+      ? @md.make
+      : nil
+    end
+    def cmd_rc_act #command-line rc
+      @cmd_rc_act=@md.opt.opt_act
+    end
+    def build
+      def ocn?
+        if cmd_rc_act[:ocn][:set]==:on
+          true
+        elsif cmd_rc_act[:ocn][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.ocn? \
+        and doc_rc.toc? ==:off
+          false
+        elsif env_rc.build.ocn? ==:off
+          false
+        else
+          true
+        end
+      end
+      def plaintext_ocn?
+        if cmd_rc_act[:txt_ocn][:set]==:on \
+        or cmd_rc_act[:ocn][:set]==:on
+          true
+        elsif cmd_rc_act[:txt_ocn][:set]==:off \
+        or cmd_rc_act[:ocn][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.ocn? \
+        and doc_rc.toc? ==:off
+          false
+        elsif env_rc.build.ocn? ==:off
+          false
+        else
+          true
+        end
+      end
+      def odt_ocn?
+        if cmd_rc_act[:odt_ocn][:set]==:on \
+        or cmd_rc_act[:ocn][:set]==:on
+          true
+        elsif cmd_rc_act[:odt_ocn][:set]==:off \
+        or cmd_rc_act[:ocn][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.ocn? \
+        and doc_rc.toc? ==:off
+          false
+        elsif env_rc.build.ocn? ==:off
+          false
+        else
+          true
+        end
+      end
+      def html_strict?
+        if cmd_rc_act[:html_strict][:set]==:on
+          true
+        elsif cmd_rc_act[:html_strict][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_strict? \
+        and doc_rc.html_strict? ==:on
+          true
+        else
+          false
+        end
+      end
+      def toc?
+        if cmd_rc_act[:toc][:set]==:on
+          true
+        elsif cmd_rc_act[:toc][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.toc? \
+        and doc_rc.toc? ==:off
+          false
+        elsif env_rc.build.toc? ==:off
+          false
+        else
+          true
+        end
+      end
+      def manifest?
+        if cmd_rc_act[:manifest][:set]==:on
+          true
+        elsif cmd_rc_act[:manifest][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.manifest? \
+        and doc_rc.manifest? ==:off
+          false
+        elsif env_rc.build.manifest? ==:off
+          false
+        else
+          true
+        end
+      end
+      def links_to_manifest?
+        if cmd_rc_act[:links_to_manifest][:set]==:on
+          true
+        elsif cmd_rc_act[:links_to_manifest][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.links_to_manifest? \
+        and doc_rc.links_to_manifest? ==:off
+          false
+        elsif env_rc.build.links_to_manifest? ==:off
+          false
+        else
+          true
+        end
+      end
+      def metadata?
+        if cmd_rc_act[:metadata][:set]==:on
+          true
+        elsif cmd_rc_act[:metadata][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.metadata? \
+        and doc_rc.metadata? ==:off
+          false
+        elsif env_rc.build.metadata? ==:off
+          false
+        else
+          true
+        end
+      end
+      def minitoc?
+        if html_top_band? == false #one form of navigation necessary
+          true
+        elsif cmd_rc_act[:minitoc][:set]==:on
+          true
+        elsif cmd_rc_act[:minitoc][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.minitoc? \
+        and doc_rc.minitoc? ==:off
+          false
+        elsif env_rc.build.minitoc? ==:off
+          false
+        else
+          false
+        end
+      end
+      def manifest_minitoc?
+        if html_top_band? == false #one form of navigation necessary
+          true
+        elsif cmd_rc_act[:manifest_minitoc][:set]==:on \
+        || cmd_rc_act[:minitoc][:set]==:on
+          true
+        elsif cmd_rc_act[:manifest_minitoc][:set]==:off \
+        || cmd_rc_act[:minitoc][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.manifest_minitoc? \
+        and (doc_rc.manifest_minitoc? ==:off \
+        || doc_rc.minitoc? ==:off)
+          false
+        elsif env_rc.build.manifest_minitoc? ==:off \
+        || env_rc.build.minitoc? ==:off
+          false
+        elsif minitoc? == false
+          false
+        else
+          false
+        end
+      end
+      def html_minitoc?
+        if html_top_band? == false #one form of navigation necessary
+          true
+        elsif cmd_rc_act[:html_minitoc][:set]==:on \
+        || cmd_rc_act[:minitoc][:set]==:on
+          true
+        elsif cmd_rc_act[:html_minitoc][:set]==:off \
+        || cmd_rc_act[:minitoc][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_minitoc? \
+        and (doc_rc.html_minitoc? ==:off \
+        || doc_rc.minitoc? ==:off)
+          false
+        elsif env_rc.build.html_minitoc? ==:off \
+        || env_rc.build.minitoc? ==:off
+          false
+        elsif minitoc? == false
+          false
+        else
+          false
+        end
+      end
+      def html_top_band?
+        if cmd_rc_act[:html_top_band][:set]==:on
+          true
+        elsif cmd_rc_act[:html_top_band][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_top_band? \
+        and doc_rc.html_top_band? ==:off
+          false
+        elsif env_rc.build.html_top_band? ==:off
+          false
+        else
+          true
+        end
+      end
+      def html_navigation?
+        if cmd_rc_act[:html_navigation][:set]==:on
+          true
+        elsif cmd_rc_act[:html_navigation][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_navigation? \
+        and doc_rc.html_navigation? ==:off
+          false
+        elsif env_rc.build.html_navigation? ==:off
+          false
+        else
+          true
+        end
+      end
+      def html_navigation_bar?
+        if cmd_rc_act[:html_navigation_bar][:set]==:on
+          true
+        elsif cmd_rc_act[:html_navigation_bar][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_navigation_bar? \
+        and doc_rc.html_navigation_bar? ==:off
+          false
+        elsif env_rc.build.html_navigation_bar? ==:off
+          false
+        else
+          false
+        end
+      end
+      def search_form?
+        if cmd_rc_act[:search_form][:set]==:on
+          true
+        elsif cmd_rc_act[:search_form][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_search_form? \
+        and doc_rc.search_form? ==:off
+          false
+        elsif env_rc.build.search_form? ==:off
+          false
+        else
+          true
+        end
+      end
+      def html_search_form?
+        if cmd_rc_act[:html_search_form][:set]==:on \
+        || cmd_rc_act[:search_form][:set]==:on
+          true
+        elsif cmd_rc_act[:html_search_form][:set]==:off \
+        || cmd_rc_act[:search_form][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_search_form? \
+        and (doc_rc.html_search_form? ==:off \
+        || doc_rc.search_form? ==:off)
+          false
+        elsif env_rc.build.html_search_form? ==:off \
+        || env_rc.build.search_form? ==:off
+          false
+        elsif search_form? == false
+          false
+        else
+          true
+        end
+      end
+      def html_right_pane?
+        if cmd_rc_act[:html_right_pane][:set]==:on
+          true
+        elsif cmd_rc_act[:html_right_pane][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.html_right_pane? \
+        and doc_rc.html_right_pane? ==:off
+          false
+        elsif env_rc.build.html_right_pane? ==:off
+          false
+        else
+          true
+        end
+      end
+      def segsubtoc?
+        if cmd_rc_act[:segsubtoc][:set]==:on
+          true
+        elsif cmd_rc_act[:segsubtoc][:set]==:off
+          false
+        elsif doc_rc.is_a?(Method) \
+        and defined? doc_rc.segsubtoc? \
+        and doc_rc.segsubtoc? ==:off
+          false
+        elsif env_rc.build.segsubtoc? ==:off
+          false
+        else
+          true
+        end
+      end
+      self
+    end
+    def ocn_html_identifier
+      (build.html_strict?) \
+      ? Mx[:ocn_id_char]
+      : ''
+    end
+    def output_dir_structure
+      def by_language_code?
+        if cmd_rc_act[:output_by][:set] == :language
+          true
+        elsif cmd_rc_act[:output_by][:set] == :filetype \
+        or cmd_rc_act[:output_by][:set] == :filename
+          false
+        elsif cmd_rc_act[:output_by][:set] == :language
+          true
+        else
+          env_rc.output_dir_structure.by_language_code?
+        end
+      end
+      def by_filetype?
+        if cmd_rc_act[:output_by][:set] == :filetype
+          true
+        elsif cmd_rc_act[:output_by][:set] == :language \
+        or cmd_rc_act[:output_by][:set] == :filename
+          false
+        elsif cmd_rc_act[:output_by][:set] == :filetype
+          true
+        else
+          env_rc.output_dir_structure.by_filetype?
+        end
+      end
+      def by_filename?
+        if cmd_rc_act[:output_by][:set] == :filename
+          true
+        elsif cmd_rc_act[:output_by][:set] == :language \
+        or cmd_rc_act[:output_by][:set] == :filetype
+          false
+        elsif cmd_rc_act[:output_by][:set] == :filename
+          true
+        else
+          env_rc.output_dir_structure.by_filename?
+        end
+      end
+      def multilingual?
+        by_language_code?
+      end
+      def dump?
+        ((cmd_rc_act[:dump][:bool] \
+        &&  cmd_rc_act[:dump][:inst]) \
+        || (env_rc.output_dir_structure.dump?)) \
+        ? true
+        : false
+      end
+      def redirect?
+        ((cmd_rc_act[:redirect][:bool] \
+        &&  cmd_rc_act[:redirect][:inst]) \
+        || (env_rc.output_dir_structure.redirect?)) \
+        ? true
+        : false
+      end
+      def dump_or_redirect?
+        ((dump?) || (redirect?)) \
+        ? true
+        : false
+      end
+      def by?
+        if dump?
+          :dump
+        elsif redirect?
+          :redirect
+        elsif by_language_code?
+          :language
+        elsif by_filetype?
+          :filetype
+        elsif by_filename?
+          :filename
+        else #recheck current default
+          :language
+        end
+      end
+      self
+    end
+  end
+end
+module SiSU_Info_Processing_Flag
+  class InfoProcessingFlag
+    attr_accessor :color,:act_0,:act_1,:act_2,:act_3,:act_4,:act_5,:act_6,:act_7,:act_8,:act_9
+    def initialize
+      @rc=SiSU_Get_Init::GetInit.new.sisu_yaml.rc
+    end
+    def color                          #configurable processing flag shortcuts
+      (defined? @rc['flag']['color']) \
+      ? @rc['flag']['color']
+      : false
+    end
+    def act_0                           #configurable processing flag shortcuts
+      def default
+        '--manifest --digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --sqlite --verbose'
+      end
+      def str
+        if defined? @rc['flag']['act0'] \
+        and @rc['flag']['act0'].is_a?(String)
+          @rc['flag']['act0']
+        elsif defined? @rc['flag']['default'] \
+        and @rc['flag']['default'].is_a?(String)
+          @rc['flag']['default']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_1                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html'
+      end
+      def str
+        if defined? @rc['flag']['act1'] \
+        and @rc['flag']['act1'].is_a?(String)
+          @rc['flag']['act1']
+        elsif defined? @rc['flag']['i'] \
+        and @rc['flag']['i'].is_a?(String)
+          @rc['flag']['i']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_2                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf'
+      end
+      def str
+        if defined? @rc['flag']['act2'] \
+        and @rc['flag']['act2'].is_a?(String)
+          @rc['flag']['act2']
+        elsif defined? @rc['flag']['ii'] \
+        and @rc['flag']['ii'].is_a?(String)
+          @rc['flag']['ii']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_3                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode'
+      end
+      def str
+        if defined? @rc['flag']['act3'] \
+        and @rc['flag']['act3'].is_a?(String)
+          @rc['flag']['act3']
+        elsif defined? @rc['flag']['iii'] \
+        and @rc['flag']['iii'].is_a?(String)
+          @rc['flag']['iii']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_4                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook'
+      end
+      def str
+        if defined? @rc['flag']['act4'] \
+        and @rc['flag']['act4'].is_a?(String)
+          @rc['flag']['act4']
+        elsif defined? @rc['flag']['iv'] \
+        and @rc['flag']['iv'].is_a?(String)
+          @rc['flag']['iv']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_5                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook --sqlite'
+      end
+      def str
+        if defined? @rc['flag']['act5'] \
+        and @rc['flag']['act5'].is_a?(String)
+          @rc['flag']['act5']
+        elsif defined? @rc['flag']['v'] \
+        and @rc['flag']['v'].is_a?(String)
+          @rc['flag']['v']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_6                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook --sqlite --xhtml --xml-sax --xml-dom'
+      end
+      def str
+        if defined? @rc['flag']['act6'] \
+        and @rc['flag']['act6'].is_a?(String)
+          @rc['flag']['act6']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_7                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook --sqlite --xhtml --xml-sax --xml-dom --source --sisupod'
+      end
+      def str
+        if defined? @rc['flag']['act7'] \
+        and @rc['flag']['act7'].is_a?(String)
+          @rc['flag']['act7']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_8                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook --xhtml --xml-sax --xml-dom --pg --update'
+      end
+      def str
+        if defined? @rc['flag']['act8'] \
+        and @rc['flag']['act8'].is_a?(String)
+          @rc['flag']['act8']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_9                           #configurable processing flag shortcuts
+      def default
+        '--manifest --text --html --epub --pdf --concordance --qrcode --digest --odf --docbook --xhtml --xml-sax --xml-dom --pg --update --source --sisupod'
+      end
+      def str
+        if defined? @rc['flag']['act9'] \
+        and @rc['flag']['act9'].is_a?(String)
+          @rc['flag']['act9']
+        else default
+        end
+      end
+      def arr
+        str.scan(/\S+/)
+      end
+      self
+    end
+    def act_info
+      puts 'current "act" settings:'
+      acts=%w[ act_0 act_1 act_2 act_3 act_4 act_5 act_6 act_7 act_8 act_9 ]
+      acts.each_with_index do |m,i|
+        puts '--act-' + i.to_s + ' == ' \
+        + send(m).str
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_programs.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_programs.rb"
+# <>
+module SiSU_Sys_Call
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  class SystemCall
+    @@locale_flag=false
+    def initialize(input='',output='',opt_or_cmd='')
+      @input,@output=input,output
+      (opt_or_cmd.is_a?(SiSU_Commandline::Options)) \
+      ? (@cmd,@opt=opt_or_cmd.cmd,opt_or_cmd)
+      : (@cmd,@opt=opt_or_cmd,nil) #cmd.is_a?(String)
+      @prog=SiSU_Env::InfoProgram.new
+      @sys=SiSU_Info_Sys::InfoSystem.instance
+    end
+    def program_found?(program)
+      found=`which #{program} 2>&1` #`whereis #{program}`
+      (found =~/bin\/#{program}\b/) ? true : false
+    end
+    def locale                         #locales utf8 or other
+      unless @@locale_flag
+        @@locale_flag=true
+      end
+      @sys.locale
+    end
+    def file_encoding(filename,act='') #file encoding
+      program='file'
+      fnsp=SiSU_Env::InfoEnv.new(filename).source_file_with_path
+      if program_found?(program)
+        encoding=%x{file -L #{fnsp}}.strip
+        encoding=encoding.gsub(/#{fnsp}:(\s+|$)/,'')
+        encoding=if encoding \
+        and not encoding.empty?
+          encoding
+        else 'UTF-8 assumed, encoding undetermined'
+        end
+        if act[:verbose_plus][:set] ==:on \
+        or  act[:maintenance][:set] ==:on
+          puts encoding
+        end
+        encoding
+      else
+        'UTF-8 assumed, file encoding check program unavailable'
+      end
+    end
+    def wc                             #word count
+      program='wc'
+      if program_found?(program) \
+      and locale !~/utf-?8/i
+        true
+      else
+        program_ref="(not available)" \
+          unless program_found?(program)
+        program_ref="(UTF-8)" \
+          if locale =~/utf-?8/i
+        false
+      end
+    end
+    def rcs                            #rcs for document markup data
+      program='rcs'
+      program_ref="\n\t\tdocument version information requested"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def cvs                            #cvs for document markup data
+      program='cvs'
+      program_ref="\n\t\tdocument version information requested"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def po4a                           #po4a
+      program='po4a'
+      program_ref="\n\t\tpo4a"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def zip                            #zip
+      program='zip'
+      program_ref="\n\t\tused to in the making of number of file formats, odf, epub"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          mark("*WARN* #{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def openssl                        #openssl for digests
+      program='openssl'
+      program_ref="\n\t\tused to generate requested source document identification digest"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def md5(filename)                  #md5 dgst
+      program='openssl'
+      program_ref="\n\t\tmd5 digest requested"
+      if program_found?(program)
+        pwd=Dir.pwd
+        Dir.chdir(File.dirname(filename))
+        dgst=%x{openssl dgst -md5 #{File.basename(filename)}}.strip #use file name without file path
+        Dir.chdir(pwd)
+        dgst.scan(/\S+/)
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def sha256(filename)               #sha dgst
+      program='openssl'
+      program_ref="\n\t\tsha digest requested"
+      if program_found?(program)
+        pwd=Dir.pwd
+        Dir.chdir(File.dirname(filename))
+        dgst=%x{openssl dgst -sha256 #{File.basename(filename)}}.strip #use file name without file path
+        Dir.chdir(pwd)
+        dgst.scan(/\S+/)
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def sha512(filename)               #sha dgst
+      program='openssl'
+      program_ref="\n\t\tsha digest requested"
+      if program_found?(program)
+        pwd=Dir.pwd
+        Dir.chdir(File.dirname(filename))
+        dgst=%x{openssl dgst -sha512 #{File.basename(filename)}}.strip #use file name without file path
+        Dir.chdir(pwd)
+        dgst.scan(/\S+/)
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def psql                           #psql
+      program='psql'
+      program_ref="\n\t\tpsql requested"
+      if program_found?(program); true
+      else
+        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+          warn("#{program} is not installed #{program_ref}")
+        false
+      end
+    end
+    def create_pg_db(dbname_stub=nil)  #createdb
+      unless dbname_stub
+        @pwd ||=Dir.pwd
+        m=/.+\/(?:src\/)?(\S+)/im # m=/.+?\/(?:src\/)?([^\/]+)$/im # m=/.+\/(\S+)/m
+        dbname_stub=@pwd[m,1]
+      end
+      program='createdb'
+      db_name="#{Db[:name_prefix]}#{dbname_stub}"
+      program_ref="\n\t\tcreatedb dbname #{db_name} #for postgresql database creation"
+      (program_found?(program)) \
+      ? system("#{program} #{dbname_name}")
+      : (STDERR.puts "\t*WARN* #{program} is not available #{program_ref}")
+    end
+    def relaxng(cmd='')                #trang - convert between different schema languages for XML
+      program='trang'
+      program_ref="\n\t\tsee "
+      (program_found?(program)) \
+      ? system("#{program} #{@input} #{@output}")
+      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" if cmd =~/V/)
+    end
+    def qrencode                       #qrcode - for generating QR code
+      program='qrencode'
+      program_ref="\n\t\tsee "
+      found=(program_found?(program)) ? true : false
+      found \
+      ? (system(%{
+          echo "#{@input}" | #{program} -s 3 -o #{@output}
+        }))
+      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" if @cmd =~/V/)
+      #found
+    end
+    def imagemagick                    #imagemagick is a image manipulation program
+      program='identify'
+      #program_ref="\n\t\tsee  "
+      found=(program_found?(program)) ? true : false
+      #STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" unless found
+      found
+    end
+    def graphicsmagick                #graphicsmagick is a image manipulation program
+      program='gm'
+      #program_ref="\n\t\tsee  "
+      found=(program_found?(program)) ? true : false
+      #STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" unless found
+      found
+    end
+    def well_formed?                   #tidy - check for well formed xml xhtml etc.
+      program=@prog.tidy
+      program_ref="\n\t\tsee  "
+      (program_found?(program)) \
+      ? system("#{@prog.tidy} -xml #{@input} > #{@output}")
+      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}")
+    end
+    def tex2pdf_engine
+      progs=['xetex','xelatex','pdflatex','pdfetex','pdftex']
+      @pdfetex_flag=false
+      @cmd ||=''
+      @texpdf=nil
+      progs.each do |program|
+        if program_found?(program)
+          @texpdf=program if program =~/xetex|xelatex|pdftex|pdflatex/
+          @pdfetex_flag=true
+          break
+        end
+      end
+      if @pdfetex_flag==false
+        @texpdf=progs.join(', ')
+      end
+      @texpdf
+    end
+    def latex2pdf(md,papersize='a4')   #convert from latex to pdf
+      tell=if @cmd =~/[MV]/
+        ''
+      elsif @cmd =~/[v]/
+        %q{2>&1 | grep -v ' WARNING '}
+      else %q{2>&1 | grep -v '$'}
+      end
+      mode='batchmode' #mode='nonstopmode'
+      texpdf=tex2pdf_engine
+      if @pdfetex_flag
+        texpdf_cmd=case texpdf
+        when /xetex/
+          %{#{texpdf} -interaction=#{mode} -fmt=xelatex #{@input} #{tell}\n}
+        when /xelatex/
+          %{#{texpdf} -interaction=#{mode} -papersize="#{papersize}" #{@input} #{tell}\n}
+        when /pdftex/
+          "#{texpdf} -interaction=#{mode} -fmt=pdflatex #{@input} #{tell}\n"
+        when /pdflatex/
+          "#{texpdf} -interaction=#{mode} #{@input} #{tell}\n"
+        end
+        system(texpdf_cmd)
+      else STDERR.puts "\t*WARN* none of the following programs are installed: #{@texpdf}"
+      end
+    end
+    def makeinfo                       #texinfo
+      program='makeinfo'
+      options='' #'--force' #''
+      program_ref="\n\t\tsee http://www.gnu.org/software/texinfo/"
+      (program_found?(program)) \
+      ? system("#{program} #{options} #{@input}\n")
+      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}")
+    end
+    def scp
+      puts "scp -Cr #{@input} #{@output}" if @cmd =~/[vVM]/
+      puts "scp disabled"
+    end
+    def rsync(action='',chdir=nil)
+      program='rsync'
+      if program_found?(program)
+        vb=if @cmd =~/q/; 'q'
+        elsif @cmd =~/v/; 'v'
+        else              ''
+        end
+        cX=SiSU_Screen::Ansi.new(@cmd).cX
+        msg=(@cmd =~/q/) ? '' : %{ && echo " #{cX.grey}OK: #{@input} -> #{@output}#{cX.off}"}
+        amp=(@opt \
+        && @opt.files.length > 1) \
+        ? ''
+        : ((@cmd =~/[vVM]/) ? '' : '&')
+        rsync_cmd="rsync -az#{vb} #{action} #{@input} #{@output}"
+        puts rsync_cmd if @cmd =~/[vVM]/
+        dir_change=dir_return=nil
+        if not chdir.nil? \
+        && chdir != Dir.pwd
+          dir_change=Dir.chdir(chdir)
+          dir_return=Dir.pwd
+        end
+        dir_change if dir_change
+        system("
+          #{rsync_cmd} #{msg} #{amp}
+        ")
+        dir_return if dir_return
+      else STDERR.puts "\t*WARN* #{program} not found"
+      end
+    end
+    def rm
+      if @cmd =~/^-Z[mMvVq]*$/;      FileUtils::rm_rf(@input)
+      elsif @cmd =~/V/;              FileUtils::rm(@input)
+      elsif @cmd !~/q/;              FileUtils::rm(@input)
+      elsif @cmd =~/q/;              FileUtils::rm(@input)
+      else                           STDERR.puts "\t*WARN* operation ignored"
+      end
+    end
+  end
+end
+module SiSU_Info_Program
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class InfoProgram < SiSU_Info_Env::InfoEnv               # se_info_env.rb
+    attr_accessor :editor,:wc,:tidy,:rexml,:pdflatex,:postgresql,:sqlite
+    def initialize
+      prog=SiSU_Env::InfoEnv.new.program
+      @editor,           @wc,    @tidy,    @rexml,    @pdflatex,    @postgresql,    @sqlite=
+        prog.text_editor,prog.wc,prog.tidy,prog.rexml,prog.pdflatex,prog.postgresql,prog.sqlite
+    end
+  end
+end
+module SiSU_Info_Set
+  require_relative 'se_info_env'                           # se_info_env.rb
+  class InfoSettings < SiSU_Info_Env::InfoEnv              # se_info_env.rb
+    def permission?(prog)                                  # program defaults
+      (defined? @rc['permission_set'][prog]) \
+      ? @rc['permission_set'][prog]
+      : false
+    end
+    def program?(prog)                                     # program defaults
+      (defined? @rc['program_set'][prog]) \
+      ? @rc['program_set'][prog]
+      : false
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_remotes.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_remotes.rb"
+# <>
+module SiSU_Info_Remote_Host
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  class InfoRemoteHost
+    def initialize
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+    end
+    def remote_host #see InfoRemote remote_host_base_general
+      r=[]
+      r=if (defined? @rc['remote'] \
+      and @rc['remote'].is_a?(Array))
+        r_array=@rc['remote']
+        r_array.each_with_index do |renv,i|
+          r[i]={}
+          if defined? renv['user'] \
+          and defined? renv['host']
+          end
+          r[i][:user]=renv['user']
+          r[i][:host]=renv['host']
+          r[i][:path]=if defined? renv['path']
+            renv['path']
+          else ''
+          end
+          r[i][:name]="#{r[i][:user]}@#{r[i][:host]}:#{r[i][:path]}"
+        end
+        r
+      elsif (defined? @rc['remote'] \
+      and @rc['remote'].is_a?(Hash) \
+      and defined? @rc['remote']['user'] \
+      and defined? @rc['remote']['host'])
+        r[0]={}
+        r[0][:user]=@rc['remote']['user']
+        r[0][:host]=@rc['remote']['host']
+        r[0][:path]=if defined? @rc['remote']['path']
+          @rc['remote']['path']
+        else ''
+        end
+        r[0][:name]="#{r[0][:user]}@#{r[0][:host]}:#{r[0][:path]}"
+        r
+      else
+        r[0]={}
+        r[0][:name]='.'
+        r[0][:user]=''
+        r[0][:host]=''
+        r[0][:path]=''
+        #puts "no remote host or user"
+        r
+      end
+    end
+    def rhost
+      def r1
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[0][:name]) \
+        ? (SiSU_Env::InfoRemoteHost.new.remote_host[0][:name])
+        : nil
+      end
+      def r2
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[1][:name]) \
+        ? (SiSU_Env::InfoRemoteHost.new.remote_host[1][:name])
+        : nil
+      end
+      def r3
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[2][:name]) \
+        ? (SiSU_Env::InfoRemoteHost.new.remote_host[2][:name])
+        : nil
+      end
+      def r4
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[3][:name]) \
+        ? (SiSU_Env::InfoRemoteHost.new.remote_host[3][:name])
+        : nil
+      end
+      def r5
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[4][:name]) \
+        ? (SiSU_Env::InfoRemoteHost.new.remote_host[4][:name])
+        : nil
+      end
+      def r6
+        (defined? SiSU_Env::InfoRemoteHost.new.remote_host[5][:name]) \
+        ? (@ls + SiSU_Env::InfoRemoteHost.new.remote_host[5][:name])
+         : nil
+      end
+      self
+    end
+  end
+end
+module SiSU_Info_Remote
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_filemap'                            # se_filemap.rb
+  begin
+    require 'fileutils'
+      include FileUtils::Verbose
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('fileutils NOT FOUND (LoadError)')
+  end
+  class InfoRemote < SiSU_File_Map::FileMap                # se_filemap.rb
+    @@flag_remote=false
+    begin
+      require 'socket'
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('socket NOT FOUND (LoadError)')
+    end
+    def initialize(opt)
+      super(opt) #
+      @opt=opt
+      @rc=GetInit.new.sisu_yaml.rc
+    end
+    def remote_host_base_general
+      SiSU_Env::InfoRemoteHost.new.remote_host
+    end
+    def remote_host_base
+      remote_host_base_general.each do |remote_conn|
+        @@flag_remote=true if remote_conn[:name] =~/\S+?@\S+/
+      end
+      remote_host_base_general
+    end
+    def scp                            #sort out later using ruby libraries #not ideal, first time each file is sent, -r must be called separately for subdir to be built
+      def document
+        self.remote_host_base.each do |remote_conn|
+          local_gen=@source_path
+          remote_gen=case @opt.cmd
+          when /u/
+            remote_conn[:name] + '/' \
+              + @env.path.base_markup_dir_stub + '/.'             #creates remote directory tree, this is not the usual function of u
+          when /[abhHNopwxXy]/
+            remote_conn[:name] + '/' \
+              + @env.path.base_markup_dir_stub + '/' \
+              + @fnb + '/.'
+          else
+            remote_conn[:name] + '/' \
+              + @env.path.base_markup_dir_stub \
+              + '/.'
+          end
+          local_epub=@source_path_epub
+          local_src=@source_path_src
+          local_pod=@source_path_pod
+          remote_epub=
+            remote_conn[:name] + '/' + @env.path.stub_epub + '/.'
+          remote_src=
+            remote_conn[:name] + '/' + @env.path.stub_src + '/.'
+          remote_pod=
+            remote_conn[:name] + '/' + @env.path.stub_pod + '/.'
+          src_txt=@opt.fnc
+          src_pod=@opt.fncb.gsub(/(\.ss[mt])(?:\.sst)?$/,'\1.txz')
+          if (local_gen =~/\S/ \
+          and local_gen !~/\/\//) \
+          and (remote_gen =~/\S/ \
+          and remote_gen !~/\/\//) \
+          and @@flag_remote==true \
+          and @opt.cmd !~/U/
+            SiSU_Env::SystemCall.new(local_gen,remote_gen).scp
+            if FileTest.file?("#{local_src}/#{src_txt}")
+              SiSU_Env::SystemCall.new("#{local_src}/#{src_txt}",remote_src).scp
+            end
+            if FileTest.file?("#{local_pod}/#{src_pod}")
+              SiSU_Env::SystemCall.new("#{local_src}/#{src_pod}",remote_pod).scp
+            end
+            if FileTest.file?("#{local_epub}/#{@opt.fnb}.epub")
+              SiSU_Env::SystemCall.new(
+                "#{local_epub}/#{@opt.fnb}.epub",
+                remote_epub,@opt.cmd
+              ).scp
+            end
+          elsif  @opt.cmd =~/U/
+            puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+            puts "#{local_gen} -> #{remote_gen}"
+            if FileTest.file?("#{local_src}/#{src_doc}")
+              puts "#{local_src}/#{src_doc}* -> #{remote_src}"
+            end
+            if FileTest.file?("#{local_pod}/#{src_doc}.txz")
+              puts "#{local_pod}/#{src_doc}* -> #{remote_pod}"
+            end
+          else
+            puts 'suspect scp request, ignored'
+            puts "#{local_gen} -> #{remote_gen} remote flag: #{@@flag_remote}"
+            puts "permission not granted #{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+          end
+        end
+      end
+      def site_base                    #base site
+        self.remote_host_base.each do |remote_conn|
+          local=@source_path
+          remote="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}/."
+          if defined? @rc['permission_set']['remote_base_site'] \
+          and @rc['permission_set']['remote_base_site'] \
+          and @@flag_remote==true \
+          and @opt.cmd !~/U/
+            puts "begin scp_base: #{local} -> #{remote}"
+            SiSU_Env::SystemCall.new("#{local}/#{@env.path.style}/",remote).scp
+          elsif @opt.cmd =~/U/
+            puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+            puts "begin scp_base: #{local} -> #{remote}"
+            puts "#{local}/#{@env.path.style}/ -> #{remote}"
+          else  puts "permission not granted #{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+          end
+        end
+      end
+      def site_base_all                #base site
+        self.remote_host_base.each do |remote_conn|
+          local=@source_path
+          remote=
+            remote_conn[:name] + '/' \
+              + @env.path.base_markup_dir_stub + '/.'
+          if defined? @rc['permission_set']['remote_base_site'] \
+          and @rc['permission_set']['remote_base_site'] \
+          and @@flag_remote==true \
+          and @opt.cmd !~/U/
+            puts "begin scp_base_all: #{local} -> #{remote}"
+            SiSU_Env::SystemCall.new("#{local}/_sisu/image_sys/",remote).scp
+            SiSU_Env::SystemCall.new("#{local}/_sisu/image/",remote).scp
+            SiSU_Env::SystemCall.new("#{local}/#{@env.path.style}/",remote).scp
+          elsif @opt.cmd =~/U/
+            puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+            puts "scp_base_all: #{local} -> #{remote}"
+            puts "#{local}/_sisu/image_sys/ -> #{remote}"
+            puts "#{local}/_sisu/image/ -> #{remote}"
+            puts "#{local}/#{@env.path.style}/ -> #{remote}"
+          else
+            puts "permission not granted #{__FILE__} #{__LINE__}" \
+              if @opt.cmd =~/M/
+          end
+        end
+      end
+      self
+    end
+    def rsync
+      def document
+        f=(@opt.act[:ao][:set]==:on) \
+        ? SiSU_Env::FileOp.new(@md)
+        : nil
+        if f
+          self.remote_host_base.each do |remote_conn|
+            local_gen=@source_path
+            #local_gen_image="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/image"
+            #local_gen_image_external="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/image_external"
+            remote_gen=
+              remote_conn[:name] + '/' \
+                + @env.path.base_markup_dir_stub + '/.'
+            remote_rel=
+              remote_conn[:name] + '/' \
+                + f.output_path.stub.rcp
+            @opt.fnc
+            if (local_gen =~/\S/ \
+            and local_gen !~/\/\//) \
+            and (remote_gen =~/\S/ \
+            and remote_gen !~/\/\//) \
+            and @@flag_remote==true \
+            and @opt.cmd !~/U/
+#             SiSU_Env::SystemCall.new("#{local_src}/#{src_txt}",remote_src,@opt.cmd).rsync
+              #delete_extra_files='--delete' # '--delete-after'
+              inp=[]
+              if (@opt.act[:html][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.html_scroll.dir)
+                inp \
+                  << f.output_path.html_seg.rel \
+                  << f.place_file.html_scroll.rel
+              end
+              if (@opt.act[:concordance][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.html_concordance.dir)
+                inp << f.place_file.html_concordance.rel
+              end
+              if (@opt.act[:epub][:set]==:on \
+              || @opt.cmd =~/^-R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.epub.dir)
+                inp << f.place_file.epub.rel
+              end
+              if (@opt.act[:odt][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.odt.dir)
+                inp << f.place_file.odt.rel
+              end
+              if (@opt.act[:xhtml][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.xhtml.dir)
+                inp << f.place_file.xhtml.rel
+              end
+              if (@opt.act[:xml_sax][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.xml_sax.dir)
+                inp << f.place_file.xml_sax.rel
+              end
+              if (@opt.act[:xml_dom][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.xml_dom.dir)
+                inp << f.place_file.xml_dom.rel
+              end
+              if (@opt.act[:xml_scaffold_structure_sisu][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.xml_scaffold_structure_sisu.dir)
+                inp << f.place_file.xml_scaffold_structure_sisu.rel
+              end
+              if (@opt.act[:xml_scaffold_structure_collapse][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.xml_scaffold_structure_collapse.dir)
+                inp << f.place_file.xml_scaffold_structure_collapse.rel
+              end
+              if (@opt.act[:txt][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.txt.dir)
+                inp << f.place_file.txt.rel
+              end
+              if (@opt.act[:manpage][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*i[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.manpage.dir)
+                inp << f.place_file.manpage.rel
+              end
+              if (@opt.act[:texinfo][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*I[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.info.dir)
+                inp << f.place_file.info.rel
+              end
+              if (@opt.act[:hash_digests][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.hash_digest.dir)
+                inp << f.place_file.hash_digest.rel
+              end
+              if (@opt.act[:share_source][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.src.dir)
+                inp << f.place_file.src.rel
+              end
+              if (@opt.act[:sisupod][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.sisupod.dir)
+                inp << f.place_file.sisupod.rel
+              end
+              if (@opt.act[:pdf][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/)
+                inp <<=(@opt.dir_structure_by == :filename) \
+                ? (f.output_path.pdf.rel + '/*.pdf')
+                : (f.output_path.pdf.rel + '/' + @opt.fnb + '*.pdf')
+              end
+              if (@opt.act[:sqlite_discrete][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.sqlite_discrete.dir)
+                inp << f.place_file.sqlite_discrete.rel
+              end
+              if (@opt.act[:qrcode][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.qrcode_md.dir)
+                inp \
+                  << f.place_file.qrcode_md.rel \
+                  << f.place_file.qrcode_title.rel
+              end
+              if (@opt.act[:manifest][:set]==:on \
+              || @opt.cmd =~/^-[mqvVM]*R[mqvVM]*$/) \
+              && FileTest.file?(f.place_file.manifest.dir)
+                inp << f.place_file.manifest.rel
+              end
+              local_gen=if inp.length > 0
+                inp.join(' ')
+              else ''
+              end
+              local_css,images,images_system='','',''
+              images=images_skin=images_system=local_css=''
+              if @opt.cmd =~/[hwbxX]/ \
+              && (defined? @md.ec[:image]) \
+              && (@md.ec[:image].length > 0)
+                images=
+                  f.place_file.images.rel + '/' \
+                    + @md.ec[:image].join(" #{f.output_path.images.rel}/")
+              end
+              if @opt.cmd =~/[yhwbxX]/ \
+              && (defined? @md.ec[:image]) \
+              && (@md.ec[:image].length > 0)
+                local_css=f.output_path.css.rel
+                images_system='_sisu/image_sys'
+              end
+              begin
+                ##create file structure without copying files?:
+                ##rsync -av -f"+ */" -f"- *" f.output_path.base.dir remote:./path/.
+                #local_dirs=%{-f"+ */" -f"- *" #{f.output_path.base.dir}/*}
+                #SiSU_Env::SystemCall.new(local_dirs,remote_gen,@opt.cmd).rsync
+                local=local_gen + ' ' + images + ' ' + images_skin + ' ' + images_system + ' ' + local_css
+                SiSU_Env::SystemCall.new(local,remote_rel,@opt.cmd).
+                  rsync('--relative',f.output_path.base.dir)
+              rescue
+                p __LINE__.to_s + ':' + __FILE__
+                local_dirs=%{--include='*/' --exclude='*' #{f.output_path.base.dir}}
+                SiSU_Env::SystemCall.new(local_dirs,remote_gen,@opt.cmd).rsync
+              end
+            elsif @opt.cmd =~/U/
+              puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+              puts "#{local_gen} -> #{remote_gen}"
+              if FileTest.file?("#{local_src}/#{src_doc}") \
+              or FileTest.file?("#{local_src}/#{src_doc}.txz")
+                puts "#{local_src}/#{src_doc}* -> #{remote_src}"
+              end
+            else
+              puts 'suspect rsync request, ignored'
+              puts "#{local_gen} -> #{remote_gen} remote flag: #{@@flag_remote}"
+              puts "permission not granted #{__FILE__} #{__LINE__}" \
+                if @opt.cmd =~/M/
+            end
+          end
+        end
+      end
+      def site_harvest
+        self.remote_host_base.each do |remote_conn|
+          local=@source_path_harvest
+          l_rel="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}"
+          lng='en'
+          if @env.output_dir_structure.by? == :language
+            ldest=lng + '/manifest'
+            files=
+              ldest + '/authors.html' + ' ' \
+                + ldest + '/topics.html'
+          elsif @env.output_dir_structure.by? == :filetype
+            ldest="manifest"
+            files=
+              ldest + '/authors.' + lng + '.html' + ' ' \
+                + ldest + '/topics.' + lng + '.html'
+          elsif @env.output_dir_structure.by? == :filename
+            files=
+              l_rel + '/authors.' + lng + '.html' + ' ' \
+                + l_rel + '/topics.' + lng + '.html'
+          end
+          remote="#{remote_conn[:name]}/#{@opt.base_stub}"
+          if @opt.act[:harvest][:set] \
+          && @opt.act[:rsync][:set]
+            (@env.output_dir_structure.by? == :filename) \
+            ? (SiSU_Env::SystemCall.new(files,remote).rsync)
+            : (SiSU_Env::SystemCall.new(ldest,remote).
+                rsync('--relative',l_rel))
+          elsif @opt.cmd =~/U/
+            puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+            puts "rsync_harvest: #{local} -> #{remote}"
+          else
+            puts "permission not granted #{__FILE__} #{__LINE__}" \
+              if @opt.cmd =~/M/
+          end
+        end
+      end
+      def site_base                    #base site
+        ldest='_sisu/*'
+        l_rel="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}"
+        image_sys="#{@env.path.webserv}/_sisu/image_sys"
+        self.remote_host_base.each do |remote_conn|
+          remote="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}"
+          remote_conf="#{remote_conn[:name]}/_sisu"
+            SiSU_Env::SystemCall.new(image_sys,remote_conf).rsync
+            SiSU_Env::SystemCall.new(ldest,remote).rsync('--relative',l_rel)
+        end
+      end
+      def site_base_sync
+        self.remote_host_base.each do |remote_conn|
+          local=@source_path
+          remote="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}/."
+          if defined? @rc['permission_set']['remote_base_site'] \
+          and @rc['permission_set']['remote_base_site'] \
+          and @@flag_remote==true \
+          and @opt.cmd !~/U/
+            delete_extra_files='--delete' # '--delete-after'
+            puts "begin rsync_base_sync: #{local} -> #{remote}"
+            SiSU_Env::SystemCall.new("#{local}/_sisu/image_sys/",remote).
+              rsync(delete_extra_files)
+            SiSU_Env::SystemCall.new("#{local}/_sisu/image/",remote).
+              rsync(delete_extra_files)
+            SiSU_Env::SystemCall.new("#{local}/#{@env.path.style}/",remote).
+              rsync(delete_extra_files)
+          elsif @opt.cmd =~/U/
+            puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+            puts "rsync_base_sync: #{local} -> #{remote}"
+            puts "#{local}/_sisu/image_sys/ -> #{remote}"
+            puts "#{local}/_sisu/image/ -> #{remote}"
+            puts "#{local}/#{@env.path.style}/ -> #{remote}"
+          else
+            puts "permission not granted #{__FILE__} #{__LINE__}" \
+              if @opt.cmd =~/M/
+          end
+        end
+      end
+      self
+    end
+    def rsync_sitemaps                 #sitemap directory
+      self.remote_host_base.each do |remote_conn|
+        local=
+          @source_path + '/sitemapindex.xml'
+        remote="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}/."
+        if @@flag_remote
+          delete_extra_files='--delete' # '--delete-after'
+          SiSU_Env::SystemCall.new(local,remote).rsync(delete_extra_files)
+        elsif @opt.cmd =~/U/
+          puts "#{__FILE__} #{__LINE__}" if @opt.cmd =~/M/
+          puts "rsync_sitemaps: #{local} -> #{remote}"
+        else
+          puts "permission not granted #{__FILE__} #{__LINE__}" \
+            if @opt.cmd =~/M/
+        end
+      end
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_standardise_lang.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_standardise_lang.rb"
+# <>
+@@lang_info=nil
+module SiSU_Standardise_Lang
+  class StandardiseLanguage
+    require_relative 'i18n'                  # i18n.rb
+    def initialize(l='')
+      @language=(l.nil? || l.empty?) \
+      ? SiSU_Env::InfoEnv.new.language_default_set
+      : l
+      @r=%{(?:#{Px[:lng_lst_rgx]})}
+      @lang_info=SiSU_i18n::Languages.new
+    end
+    def lang_lst                       # from i18n
+      @@lang_info ||=@lang_info.language.list
+    end
+    def lang(l='')                     # from i18n
+      if l =~/^#{@r}$/
+        @lang_info.language.list[l]
+      elsif @language =~/^#{@r}$/
+        @lang_info.language.list[@language]
+      else nil
+      end
+    end
+    def language
+      lng={}
+      case @language
+      when /^am$|Amharic/i                    then d,c,l=false,lang_lst['am'][:c],    lang_lst['am'][:n]
+      when /^bg$|Bulgarian/i                  then d,c,l=false,lang_lst['bg'][:c],    lang_lst['bg'][:n]
+      when /^bn$|Bengali/i                    then d,c,l=false,lang_lst['bn'][:c],    lang_lst['bn'][:n]
+      when /^br$|Breton/i                     then d,c,l=false,lang_lst['br'][:c],    lang_lst['br'][:n]
+      when /^ca$|Catalan/i                    then d,c,l=false,lang_lst['ca'][:c],    lang_lst['ca'][:n]
+      when /^cs$|Czech/i                      then d,c,l=false,lang_lst['cs'][:c],    lang_lst['cs'][:n]
+      when /^cy$|Welsh/i                      then d,c,l=false,lang_lst['cy'][:c],    lang_lst['cy'][:n]
+      when /^da$|Danish|Dansk/i               then d,c,l=false,lang_lst['da'][:c],    lang_lst['da'][:n]
+      when /^de$|German/i                     then d,c,l=false,lang_lst['de'][:c],    lang_lst['de'][:n]
+      when /^el$|Greek/i                      then d,c,l=false,lang_lst['el'][:c],    lang_lst['el'][:n]
+      when /^en$|English/i                    then d,c,l=false,lang_lst['en'][:c],    lang_lst['en'][:n]
+      when /^eo$|Esperanto/i                  then d,c,l=false,lang_lst['eo'][:c],    lang_lst['eo'][:n]
+      when /^es$|Spanish|Espanol/i            then d,c,l=false,lang_lst['es'][:c],    lang_lst['es'][:n]
+      when /^et$|Estonian/i                   then d,c,l=false,lang_lst['et'][:c],    lang_lst['et'][:n]
+      when /^eu$|Basque/i                     then d,c,l=false,lang_lst['eu'][:c],    lang_lst['eu'][:n]
+      when /^fi$|Finnish|Finsk|Suomi/i        then d,c,l=false,lang_lst['fi'][:c],    lang_lst['fi'][:n]
+      when /^fr$|French|Francais/i            then d,c,l=false,lang_lst['fr'][:c],    lang_lst['fr'][:n]
+      when /^ga$|Irish/i                      then d,c,l=false,lang_lst['ga'][:c],    lang_lst['ga'][:n]
+      when /^gl$|Galician/i                   then d,c,l=false,lang_lst['gl'][:c],    lang_lst['gl'][:n]
+      when /^he$|Hebrew/i                     then d,c,l=false,lang_lst['he'][:c],    lang_lst['he'][:n]
+      when /^hi$|Hindi/i                      then d,c,l=false,lang_lst['hi'][:c],    lang_lst['hi'][:n]
+      when /^hr$|Croatian/i                   then d,c,l=false,lang_lst['hr'][:c],    lang_lst['hr'][:n]
+      when /^hy$|Armenian/i                   then d,c,l=false,lang_lst['hy'][:c],    lang_lst['hy'][:n]
+      when /^ia$|Interlingua/i                then d,c,l=false,lang_lst['ia'][:c],    lang_lst['ia'][:n]
+      when /^is$|Icelandic/i                  then d,c,l=false,lang_lst['is'][:c],    lang_lst['is'][:n]
+      when /^it$|Italian/i                    then d,c,l=false,lang_lst['it'][:c],    lang_lst['it'][:n]
+      when /^la$|Latin/i                      then d,c,l=false,lang_lst['la'][:c],    lang_lst['la'][:n]
+      when /^lo$|Lao/i                        then d,c,l=false,lang_lst['lo'][:c],    lang_lst['lo'][:n]
+      when /^lt$|Lithuanian/i                 then d,c,l=false,lang_lst['lt'][:c],    lang_lst['lt'][:n]
+      when /^lv$|Latvian/i                    then d,c,l=false,lang_lst['lv'][:c],    lang_lst['lv'][:n]
+      when /^ml$|Malayalam/i                  then d,c,l=false,lang_lst['ml'][:c],    lang_lst['ml'][:n]
+      when /^mr$|Marathi/i                    then d,c,l=false,lang_lst['mr'][:c],    lang_lst['mr'][:n]
+      when /^nl$|Dutch/i                      then d,c,l=false,lang_lst['nl'][:c],    lang_lst['nl'][:n]
+      when /^no$|Norwegian|Norsk/i            then d,c,l=false,lang_lst['no'][:c],    lang_lst['no'][:n]
+      when /^nn$|Norwegian Nynorsk/i          then d,c,l=false,lang_lst['nn'][:c],    lang_lst['nn'][:n]
+      when /^oc$|Occitan/i                    then d,c,l=false,lang_lst['oc'][:c],    lang_lst['oc'][:n]
+      when /^pl$|Polish/i                     then d,c,l=false,lang_lst['pl'][:c],    lang_lst['pl'][:n]
+      when /^pt$|Portuguese/i                 then d,c,l=false,lang_lst['pt'][:c],    lang_lst['pt'][:n]
+      when /^pt_BR$|Portuguese Brazil/i       then d,c,l=false,lang_lst['pt_BR'][:c], lang_lst['pt_BR'][:n]
+      when /^ro$|Romanian/i                   then d,c,l=false,lang_lst['ro'][:c],    lang_lst['ro'][:n]
+      when /^ru$|Russian/i                    then d,c,l=false,lang_lst['ru'][:c],    lang_lst['ru'][:n]
+      when /^sa$|Sanskrit/i                   then d,c,l=false,lang_lst['sa'][:c],    lang_lst['sa'][:n]
+      when /^se$|Sami/i                       then d,c,l=false,lang_lst['se'][:c],    lang_lst['se'][:n]
+      when /^sk$|Slovak/i                     then d,c,l=false,lang_lst['sk'][:c],    lang_lst['sk'][:n]
+      when /^sl$|Slovenian/i                  then d,c,l=false,lang_lst['sl'][:c],    lang_lst['sl'][:n]
+      when /^sq$|Albanian/i                   then d,c,l=false,lang_lst['sq'][:c],    lang_lst['sq'][:n]
+      when /^sr$|Serbian/i                    then d,c,l=false,lang_lst['sr'][:c],    lang_lst['sr'][:n]
+      when /^sv$|Swedish|Svensk/i             then d,c,l=false,lang_lst['sv'][:c],    lang_lst['sv'][:n]
+      when /^ta$|Tamil/i                      then d,c,l=false,lang_lst['ta'][:c],    lang_lst['ta'][:n]
+      when /^te$|Telugu/i                     then d,c,l=false,lang_lst['te'][:c],    lang_lst['te'][:n]
+      when /^th$|Thai/i                       then d,c,l=false,lang_lst['th'][:c],    lang_lst['th'][:n]
+      when /^tk$|Turkmen/i                    then d,c,l=false,lang_lst['tk'][:c],    lang_lst['tk'][:n]
+      when /^tr$|Turkish/i                    then d,c,l=false,lang_lst['tr'][:c],    lang_lst['tr'][:n]
+      when /^uk$|Ukranian/i                   then d,c,l=false,lang_lst['uk'][:c],    lang_lst['uk'][:n]
+      when /^ur$|Urdu/i                       then d,c,l=false,lang_lst['ur'][:c],    lang_lst['ur'][:n]
+      when /^us|American$|/i                  then d,c,l=false,lang_lst['en'][:c],    lang_lst['en'][:n]
+      when /^vi$|Vietnamese/i                 then d,c,l=false,lang_lst['vi'][:c],    lang_lst['vi'][:n]
+      else                                     d,c,l=true, lang_lst['en'][:c],    lang_lst['en'][:n] #default
+      end
+      lng[:d],lng[:c],lng[:n]=d,c,l
+      lng
+    end
+    def name
+      language[:n].downcase
+    end
+    def title
+      language[:n]
+    end
+    def code
+      language[:c]
+    end
+    def tex_name
+      language[:xlp]
+    end
+    def file_to_language(file)         # used, fix and remove
+      m=/.+?\~(\w{2,3})\.(?:-|ssm\.)?sst$/
+      @language=if file =~m ; file[m,1]
+      else ''
+      end
+      language
+    end
+    def codes
+      # Language List po4a
+      #    
+      #   Px[:lng_lst] see constants.rb
+      # see polyglossia for subset
+      #   
+      # also note ISO_639-2
+      #   
+      #   
+      Px[:lng_lst] # constants.rb
+    end
+  end
+end
+__END__
+#+END_SRC
+
+** se_version.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/se_version.rb"
+# <>
+module SiSU_Info_Version
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  require_relative 'se_info_env'                           # se_info_env.rb
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  class InfoVersion < SiSU_Info_Env::InfoEnv               # se_info_env.rb
+    include Singleton
+    begin
+      require 'rbconfig'
+      require 'yaml'
+    rescue LoadError
+      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+        error('rbconfig or yaml NOT FOUND (LoadError)')
+    end
+    @@lib_path=nil
+    def get_version
+      version={}
+      @pwd=ENV['PWD']
+      lib_path=
+        @@lib_path \
+        ? @@lib_path
+        : `echo $RUBYLIB`.split(':')
+      @@lib_path ||=lib_path
+      if File.exist?(SiSU_is.version_info_path?)
+        version=YAML::load(File::open(SiSU_is.version_info_path?))
+      end
+      version[:install_method]=if SiSU_is.runtime_type? ==:gem_install
+        spec = Gem::Specification.find_by_name("sisu")
+        gem_root = spec.gem_dir
+        (File.dirname(__FILE__.gsub(/\/lib\/sisu}/,'')) == gem_root) \
+        ? ' (ruby gem install)' : ''
+      else ''
+      end
+      @version=version
+      def version_details_hash
+        @version
+      end
+      def project
+        version_details_hash[:project]
+      end
+      def date
+        version_details_hash[:date]
+      end
+      def date_stamp
+        version_details_hash[:date_stamp]
+      end
+      def version
+        version_details_hash[:version]
+      end
+      def version_major
+        @version_major=version_details_hash[:version].gsub(/([0-9]+)\.[0-9]+\.[0-9]+/,'\1')
+      end
+      def install_method
+        version_details_hash[:install_method]
+      end
+      self
+    end
+    def rbversion
+      %x{ruby -v}.strip
+    end
+  end
+end
+module SiSU_Info_About
+  require_relative 'constants'                             # constants.rb
+  require_relative 'utils'                                 # utils.rb
+  begin
+    require 'singleton'
+  rescue LoadError
+    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
+      error('singleton NOT FOUND (LoadError)')
+  end
+  class InfoAbout
+    def initialize(color='')
+      @color=color
+    end
+    def sisu_version
+      version=SiSU_Env::InfoVersion.instance.get_version
+      rb_ver=SiSU_Env::InfoVersion.instance.rbversion
+      if version.version
+        opt_cmd=if defined? @color.cmd \
+        and @color.cmd =~/[ck]/
+          @color.cmd
+        else '-v'
+        end
+        SiSU_Screen::Ansi.new(
+          opt_cmd,
+          version.project,
+          version.version,
+          version.date_stamp,
+          version.date,
+          version.install_method,
+          rb_ver
+        ).version
+      else puts 'SiSU (version information not available)'
+      end
+    end
+    def sisu_about
+      puts <<-WOK
+     sisu: documents; markup, structuring, publishing in multiple standard formats, & search
+     most (not all) useful commands (are made in a directory containing a sisu markup file &) take the form:
+       sisu [action(s)] [filename(s)]
+     where filename refers to a valid sisu marked up file, e.g.:
+       cd /usr/share/doc/sisu/markup-samples/sisu_manual
+       sisu --html --verbose sisu_commands.sst
+       sisu --txt --html --epub --odt --pdf --sqlite --manpage --texinfo --concordance --qrcode --verbose sisu.ssm
+       cd -
+     See output produced, or see man pages: man sisu
+        
+        WOK
+    end
+  end
+end
+__END__
+#+END_SRC
+
+* document header
+
+#+NAME: sisu_document_header
+#+BEGIN_SRC text
+encoding: utf-8
+- Name: SiSU
+
+  - Description: documents, structuring, processing, publishing, search
+    se
+
+  - Author: Ralph Amissah
+    
+
+  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
+    2020, 2021, Ralph Amissah,
+    All Rights Reserved.
+
+  - License: GPL 3 or later:
+
+    SiSU, a framework for document structuring, publishing and search
+
+    Copyright (C) Ralph Amissah
+
+    This program is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation, either version 3 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along with
+    this program. If not, see  .
+
+    If you have Internet connection, the latest version of the GPL should be
+    available at these locations:
+    
+    
+
+    
+
+  - SiSU uses:
+    - Standard SiSU markup syntax,
+    - Standard SiSU meta-markup syntax, and the
+    - Standard SiSU object citation numbering and system
+
+  - Homepages:
+    
+
+  - Git
+     
+    
+    
+#+END_SRC
diff --git a/org/harvest.org b/org/harvest.org
new file mode 100644
index 00000000..ccc55123
--- /dev/null
+++ b/org/harvest.org
@@ -0,0 +1,1454 @@
+-*- mode: org -*-
+#+TITLE:       sisu harvest
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :sisu:harvest:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     content hideblocks hidestars noindent entitiespretty
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+PROPERTY:    header-args  :exports code
+#+PROPERTY:    header-args+ :noweb yes
+#+PROPERTY:    header-args+ :eval no
+#+PROPERTY:    header-args+ :results no
+#+PROPERTY:    header-args+ :cache no
+#+PROPERTY:    header-args+ :padline no
+
+* harvest
+** html_harvest.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/html_harvest.rb"
+# <>
+module SiSU_Harvest
+  @@the_idx_topics,@@the_idx_authors={},{}
+  class Source
+    require_relative 'hub_options'                          # hub_options.rb
+    require_relative 'html_harvest_topics'                  # html_harvest_topics.rb
+    require_relative 'html_harvest_authors'                 # html_harvest_authors.rb
+    require_relative 'se'                                   # se.rb
+      include SiSU_Env
+    def initialize(opt)
+      @opt=opt
+      @env=SiSU_Env::InfoEnv.new
+    end
+    def read
+      begin
+        harvest_pth=@env.path.webserv + '/' + @opt.base_stub
+        FileUtils::mkdir_p(harvest_pth) unless FileTest.directory?(harvest_pth)
+        cases(@opt,@env)
+      rescue
+      ensure
+        SiSU_Env::CreateSite.new(@opt).cp_css
+      end
+    end
+    def help
+      puts <>
+module SiSU_HarvestTopics
+  require_relative 'html_harvest_author_format'          # html_harvest_author_format.rb
+  require_relative 'html_parts'                          # html_parts.rb
+  class Songsheet
+    @@the_idx_topics={}
+    def initialize(opt,env)
+      @opt,@env=opt,env
+      @file_list=opt.files
+    end
+    def songsheet
+      idx_array={}
+      @opt.f_pths.each do |y|
+        lang_hash_file_array={}
+        name=y[:f]
+        filename=y[:pth] + '/' + y[:f]
+        File.open(filename,'r') do |file|
+          file.each_line("\n\n") do |line|
+            if line =~/^@(?:title|creator|classify):(?:\s|$)/m
+              lang_hash_file_array[y[:lng_is]] ||= []
+              lang_hash_file_array[y[:lng_is]] << line
+            elsif line =~/^@\S+?:(?:\s|$)/m \
+            or line =~/^(?:\s*\n|\s*$|%+ )/
+            else break
+            end
+          end
+        end
+        lang_hash_file_array.each_pair do |lang,a|
+          idx_array[lang] ||=[]
+          idx_array=SiSU_HarvestTopics::Harvest.new(
+            @opt,
+            @env,
+            a,
+            filename,
+            name,
+            idx_array,
+            lang
+          ).extract_harvest
+        end
+      end
+      the_hash=SiSU_HarvestTopics::Index.new(
+        @opt,
+        @env,
+        idx_array,
+        @@the_idx_topics
+      ).song
+      SiSU_HarvestTopics::OutputIndex.new(
+        @opt,
+        the_hash
+      ).html_print.html_songsheet
+    end
+  end
+  class Mix
+    def spaces
+      Ax[:spaces]
+    end
+  end
+  class Harvest
+    def initialize(opt,env,data,filename,name,idx_array,lang)
+      @opt, @env,@data,@filename,@name,@idx_array,@lang=
+        opt,env, data, filename, name, idx_array, lang
+    end
+    def extract_harvest
+      data,   filename, name, idx_array, lang=
+        @data,@filename,@name,@idx_array,@lang
+      @idx_lst=@title=@subtitle=@fulltitle=@author=@author_format=nil
+      rgx={}
+      rgx[:author]=/^@creator:(?:[ ]+|.+?:author:[ ]+)(.+?)(?:\||\n)/m
+      rgx[:title]=/^@title:[ ]+(.+)/
+      rgx[:subtitle]=/^@title:.+?:subtitle:[ ]+(.+?)\n/m
+      rgx[:idx]=/^@classify:.+?:topic_register:[ ]+(.+?)(?:\n\n|\n\s+:\S|\n%)/m
+      data.each do |para|
+        if para=~ rgx[:idx]
+          @idx_list=(rgx[:idx].match(para)[1]).split(/\s*\n\s*/).join
+        end
+        if para=~ rgx[:title]
+          @title=rgx[:title].match(para)[1]
+        end
+        if para=~ rgx[:subtitle]
+          @subtitle=rgx[:subtitle].match(para)[1]
+        end
+        if para=~ rgx[:author]
+          @author_format=rgx[:author].match(para)[1]
+        end
+        break if @title && @subtitle && @author && @idx_lst
+      end
+      @fulltitle=@subtitle ? (@title + ' - ' + @subtitle) : @title
+      if @title \
+      and @author_format \
+      and @idx_list
+        creator=SiSU_FormatAuthor::Author.new(@author_format.strip).author_details
+        @authors,@authorship=creator[:authors],creator[:authorship]
+        file=if name=~/~[a-z]{2,3}\.ss[mt]$/
+          name.sub(/~[a-z]{2,3}\.ss[mt]$/,'')
+        else
+          name.sub(/\.ss[mt]$/,'')
+        end
+        page=if @env.output_dir_structure.by? == :language
+          "#{lang}/sisu_manifest.html"
+        else
+          "sisu_manifest.#{lang}.html"
+        end
+        idx_array[lang] <<=if @idx_list =~/;/
+          g=@idx_list.scan(/[^;]+/)
+          g.each.map do |i|
+            i=i.strip
+            {
+              filename: filename,
+              file: file,
+              rough_idx: i,
+              title: @fulltitle,
+              author: creator,
+              page: page,
+              lang: lang
+            }
+          end
+        else {
+            filename: filename,
+            file: file,
+            rough_idx: @idx_list,
+            title: @fulltitle,
+            author: creator,
+            page: page,
+            lang: lang,
+          }
+        end
+      else
+        if (@opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on)
+          p "missing required field in #{@filename} - [title]: <#{@title}>; [author]: <#{@author_format}>; [idx]: <#{@idx_list}>"
+        end
+      end
+      idx_array[lang]=idx_array[lang].flatten
+      idx_array
+    end
+  end
+  class Index < Mix
+    def initialize(opt,env,idx_array,the_idx)
+      @opt, @env,@idx_array,@the_idx=
+        opt,env, idx_array, the_idx
+      @@the_idx_topics=@the_idx
+    end
+    def song
+      the_idx=construct_book_topic_keys
+      construct_book_topic_hash(the_idx)
+    end
+    def capital(txt)
+      txt_a=txt.scan(/\S+/)
+      tx=''
+      txt_a.each do |t|
+        tx += t[0].chr.capitalize + t[1,txt.length] + ' '
+      end
+      tx.strip
+    end
+    def capital_(txt)
+      txt[0].chr.capitalize + txt[1,txt.length]
+    end
+    def contents(idx,lang)
+      names=''
+      idx[:author][:last_first_format_a].each do |n|
+        s=n.sub(/(.+?)(?:,.+|$)/,'\1').gsub(/\s+/,'_')
+        names=if @env.output_dir_structure.by? == :language
+          names += %{#{n} , }
+        else
+          names += %{#{n} , }
+        end
+      end
+      {
+        filename: idx[:filename],
+        file: idx[:file],
+        author: names,
+        title: idx[:title],
+        page: idx[:page]
+      }
+    end
+    def capital_(txt)
+      txt[0].chr.capitalize + txt[1,txt.length]
+    end
+    def key_create(c,alt)
+      x=nil
+      x=if c.length==6
+        c[0].to_s + '|' +
+          capital(c[1][0].to_s) + '|' +
+          capital(c[2][0].to_s) + '|' +
+          capital(c[3][0].to_s) + '|' +
+          capital(alt.to_s)
+      elsif c.length==5
+        c[0].to_s + '|' +
+          capital(c[1][0].to_s) + '|' +
+          capital(c[2][0].to_s) + '|' +
+          capital(alt.to_s)
+      elsif c.length==4
+        c[0].to_s + '|' +
+          capital(c[1][0].to_s) + '|' +
+          capital(alt.to_s)
+      elsif c.length==3
+        c[0].to_s + '|' +
+          capital(alt.to_s)
+      end
+    end
+    def construct_book_topic_keys
+      idx_array=@idx_array
+      @idx_a=[]
+      @the_a=[]
+      idx_array.each_pair do |lang,idx_arr|
+        @@the_idx_topics[lang] ||= {}
+        idx_arr.each do |idx|
+          if idx[:rough_idx]
+            idx_lst=idx[:rough_idx].scan(/[^:]+/)
+          else
+            puts "no topic register in: << #{idx[:filename]} >>"
+            next
+          end
+          idx_a=[]
+          idx_lst.each do |c|
+            idx_a << c.scan(/[^|\n]+/m)
+          end
+          idx_a << contents(idx,lang)
+          @idx_a << [lang] + idx_a
+        end
+      end
+      @idx_a.each do |c|
+        if c.length > 1 \
+        and c.is_a?(Array)
+          if c[2].is_a?(Hash)
+            c[1].each do |alt|
+              v=key_create(c,alt)
+              @the_a << [v, c[2]] if v
+            end
+          end
+        end
+        if c.length > 2 \
+        and c.is_a?(Array)
+          if c[3].is_a?(Hash)
+            c[2].each do |alt|
+              v=key_create(c,alt)
+              @the_a << [v, c[3]] if v
+            end
+          end
+        end
+        if c.length > 3 \
+        and c.is_a?(Array)
+          if c[4].is_a?(Hash)
+            c[3].each do |alt|
+              v=key_create(c,alt)
+              @the_a << [v, c[4]] if v
+            end
+          end
+        end
+        if c.length > 4 \
+        and c.is_a?(Array)
+          if c[5].is_a?(Hash)
+            c[4].each do |alt|
+              v=key_create(c,alt)
+              @the_a << [v, c[5]] if v
+            end
+          end
+        end
+        if c.length > 5 \
+        and c.is_a?(Array)
+          if c[6].is_a?(Hash)
+            c[5].each do |alt|
+              v=key_create(c,alt)
+              @the_a << [v, c[6]] if v
+            end
+          end
+        end
+      end
+      @the_a.sort_by { |x| x[0] } #; y.each {|z| puts z}
+    end
+    def construct_book_topic_hash(t)
+      @the_h={}
+      t.each do |z|
+        x=z[0].scan(/[^|]+/)
+        depth=x.length
+        extract=(depth-1)
+        k=case extract
+        when 4
+          { x[0] => { x[1] => { x[2] => { x[3] => { x[4] => z[1] } } } } }
+        when 3
+          { x[0] => { x[1] => { x[2] => { x[3] => z[1] } } } }
+        when 2
+          { x[0] => { x[1] => { x[2] => z[1] } } }
+        when 1
+          { x[0] => { x[1] => z[1] } }
+        when 0
+          { x[0] => z[1] }
+        end
+        if extract >= 0
+          k.each_pair do |x0,y0|
+            if extract == 0
+              @the_h[x0] ||={ md: [] }
+              @the_h[x0][:md] << y0
+            else
+              @the_h[x0] ||={}
+            end
+            #puts spaces*0 + x0
+            if extract >= 1
+              y0.each_pair do |x1,y1|
+                if extract == 1
+                  @the_h[x0][x1] ||={ md: [] }
+                  @the_h[x0][x1][:md] << y1
+                else
+                  @the_h[x0][x1] ||={}
+                end
+                #puts spaces*1 + x1
+                if extract >= 2
+                  y1.each_pair do |x2,y2|
+                    if extract == 2
+                      @the_h[x0][x1][x2] ||={ md: [] }
+                      @the_h[x0][x1][x2][:md] << y2
+                    else
+                      @the_h[x0][x1][x2] ||={}
+                    end
+                    #puts spaces*2 + x2
+                    if extract >= 3
+                      y2.each_pair do |x3,y3|
+                        if extract == 3
+                          @the_h[x0][x1][x2][x3] ||={ md: [] }
+                          @the_h[x0][x1][x2][x3][:md] << y3
+                        else
+                          @the_h[x0][x1][x2][x3] ||={}
+                        end
+                        #puts spaces*3 + x3
+                        if extract == 4
+                          y3.each_pair do |x4,y4|
+                            if extract == 4
+                              @the_h[x0][x1][x2][x3][x4] ||={ md: [] }
+                              @the_h[x0][x1][x2][x3][x4][:md] << y4
+                            else
+                              @the_h[x0][x1][x2][x3][x4] ||={}
+                            end
+                            #puts spaces*4 + x4
+                            if extract == 5
+                              y4.each_pair do |x5,y5|
+                                if extract == 5
+                                  @the_h[x0][x1][x2][x3][x4][x5] ||={ md: [] }
+                                  @the_h[x0][x1][x2][x3][x4][x5][:md] << y5
+                                end
+                                #puts spaces*5 + x5
+                              end
+                            end
+                          end
+                        end
+                      end
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+      #@the_h.each_pair { |x,y| p x; p y }
+      @the_h
+    end
+    def traverse_base
+      @the_h.each_pair do |x0,y0|
+        puts spaces*0 + x0 if x0.is_a?(String)
+        if y0.is_a?(Hash)
+          y0.each_pair do |x1,y1|
+            puts spaces*1 + x1 if x1.is_a?(String)
+            if y1.is_a?(Hash)
+              y1.each_pair do |x2,y2|
+                puts spaces*2 + x2 if x2.is_a?(String)
+                if y2.is_a?(Hash)
+                  y2.each_pair do |x3,y3|
+                    puts spaces*3 + x3 if x3.is_a?(String)
+                    if y3.is_a?(Hash)
+                      y3.each_pair do |x4,y4|
+                        puts spaces*4 + x4 if x4.is_a?(String)
+                        if y4.is_a?(Hash)
+                          y4.each_pair do |x5,y5|
+                            puts spaces*5 + x5 if x5.is_a?(String)
+                          end
+                        end
+                      end
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+    def traverse
+      @the_h.each_pair do |x0,y0|
+        puts spaces*0 + x0 if x0.is_a?(String)
+        if y0.is_a?(Hash)
+          if y0.has_key?(:md)
+            y0[:md].each { |x| puts spaces*5 + x[:title] }
+          end
+          y0.each_pair do |x1,y1|
+            puts spaces*1 + x1 if x1.is_a?(String)
+            if y1.is_a?(Hash)
+              if y1.has_key?(:md)
+                y1[:md].each { |x| puts spaces*5 + x[:title] }
+              end
+              y1.each_pair do |x2,y2|
+                puts spaces*2 + x2 if x2.is_a?(String)
+                if y2.is_a?(Hash)
+                  if y2.has_key?(:md)
+                    y2[:md].each { |x| puts spaces*5 + x[:title] }
+                  end
+                  y2.each_pair do |x3,y3|
+                    puts spaces*3 + x3 if x3.is_a?(String)
+                    if y3.is_a?(Hash)
+                      if y3.has_key?(:md)
+                        y3[:md].each { |x| puts spaces*5 + x[:title] }
+                      end
+                      y3.each_pair do |x4,y4|
+                        puts spaces*4 + x4 if x4.is_a?(String)
+                        if y4.is_a?(Hash)
+                          if y4.has_key?(:md)
+                            y4[:md].each { |x| puts spaces*5 + x[:title] }
+                          end
+                          y4.each_pair do |x5,y5|
+                            puts spaces*5 + x4 if x4.is_a?(String)
+                          end
+                        end
+                      end
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+  end
+  class OutputIndex < Mix
+    require_relative 'i18n'                               # i18n.rb
+    def initialize(opt,the_idx)
+      @opt,@the_idx=opt,the_idx
+      @env=SiSU_Env::InfoEnv.new
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @alphabet_list=%W[9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
+      @alph=@alphabet_list.dup
+      @letter=@alph.shift
+    end
+    def html_file_open
+      @the_idx.keys.each do |lng|
+        @output ||={}
+        @output[lng] ||={}
+        harvest_pth,file='',''
+        if @env.output_dir_structure.by? == :language
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub + '/' \
+          + lng + '/' \
+          + 'manifest'
+          file=harvest_pth + '/' + 'topics.html'
+        elsif @env.output_dir_structure.by? == :filetype
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub + '/' \
+          + 'manifest'
+          file=harvest_pth + '/' + 'topics.' + lng + '.html'
+        elsif @env.output_dir_structure.by? == :filename
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub
+          file=harvest_pth + '/' + 'topics.' + lng + '.html'
+        end
+        FileUtils::mkdir_p(harvest_pth) \
+          unless FileTest.directory?(harvest_pth)
+        fileinfo=(@opt.act[:verbose][:set]==:on \
+        || @opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:urls_selected][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on) \
+        ? ("file://#{file}")
+        : ''
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "harvest topics(#{@opt.files.length} files)",
+          fileinfo
+        ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
+        @output[lng][:html]=File.new(file,'w')
+        if @opt.act[:maintenance][:set]==:on
+          @output[lng][:html_mnt]=File.new("#{@env.path.pwd}/topics.html",'w')
+        end
+      end
+    end
+    def html_file_close
+      @the_idx.keys.each do |lng|
+        @output[lng][:html].close
+        @output[lng][:html_mnt].close if @output[lng][:html_mnt].is_a?(File)
+      end
+    end
+    def html_print
+      def html_songsheet
+        #traverse
+        html_file_open
+        html_head
+        html_alph
+        html_body_traverse
+        html_tail
+        html_file_close
+      end
+      def html_body_traverse
+        @the_idx.each_pair do |x0,y0|
+          lng=x0
+          if x0.is_a?(String)
+            #do_string_name(lng,'lev0',x0)
+            #puts spaces*0 + x0
+          end
+          if y0.is_a?(Hash)
+            if y0.has_key?(:md)
+              y0[:md].each do |x|
+                #do_hash(lng,attrib,x) #lv==0 ?
+                #puts spaces*5 + x[:title]
+              end
+            end
+            y0.each_pair do |x1,y1|
+              if x1.is_a?(String)
+                do_string_name(lng,'lev0',x1)
+                #puts spaces*1 + x1
+              end
+              if y1.is_a?(Hash)
+                if y1.has_key?(:md)
+                  y1[:md].each do |x|
+                    do_hash(lng,0,x)
+                    #puts spaces*5 + x[:title]
+                  end
+                end
+                y1.each_pair do |x2,y2|
+                  if x2.is_a?(String)
+                    do_string(lng,'lev1',x2)
+                    #puts spaces*2 + x2
+                  end
+                  if y2.is_a?(Hash)
+                    if y2.has_key?(:md)
+                      y2[:md].each do |x|
+                        do_hash(lng,1,x)
+                        #puts spaces*5 + x[:title]
+                      end
+                    end
+                    y2.each_pair do |x3,y3|
+                      if x3.is_a?(String)
+                        do_string(lng,'lev2',x3)
+                        #puts spaces*3 + x3
+                      end
+                      if y3.is_a?(Hash)
+                        if y3.has_key?(:md)
+                          y3[:md].each do |x|
+                            do_hash(lng,2,x)
+                            #puts spaces*5 + x[:title]
+                          end
+                        end
+                        y3.each_pair do |x4,y4|
+                          if x4.is_a?(String)
+                            do_string(lng,'lev3',x4)
+                            #puts spaces*4 + x4
+                          end
+                          if y4.is_a?(Hash)
+                            if y4.has_key?(:md)
+                              y4[:md].each do |x|
+                                do_hash(lng,3,x)
+                                #puts spaces*5 + x[:title]
+                              end
+                            end
+                            y4.each_pair do |x5,y5|
+                              if x5.is_a?(String)
+                                do_string(lng,'lev4',x5)
+                                #puts spaces*5 + x5
+                              end
+                            end
+                          end
+                        end
+                      end
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+      def html_head_adjust(lng,type='')
+        css_path,authors='',''
+        if @env.output_dir_structure.by? == :language
+          css_path=(type !~/maintenance/) \
+          ? '../../_sisu/css/harvest.css'
+          : 'harvest.css'
+          authors='authors.html'
+        elsif @env.output_dir_structure.by? == :filetype
+          css_path=(type !~/maintenance/) \
+          ? '../_sisu/css/harvest.css'
+          : 'harvest.css'
+          authors="authors.#{lng}.html"
+        elsif @env.output_dir_structure.by? == :filename
+          css_path=(type !~/maintenance/) \
+          ? './_sisu/css/harvest.css'
+          : 'harvest.css'
+          authors="authors.#{lng}.html"
+        end
+        ln=SiSU_i18n::Languages.new.language.list
+        harvest_languages=''
+        @the_idx.keys.each do |lg|
+          if @env.output_dir_structure.by? == :language
+            harvest_pth="../../#{lg}/manifest"
+            file=harvest_pth + '/' + 'topics.html'
+          elsif @env.output_dir_structure.by? == :filetype
+            harvest_pth='.'
+            file=harvest_pth + '/' + 'topics.' + lg + '.html'
+          elsif @env.output_dir_structure.by? == :filename
+            harvest_pth='.'
+            file=harvest_pth + '/topics.' + lg + '.html'
+          end
+          l=ln[lg][:t]
+          harvest_languages +=
+            %{#{l}    }
+        end
+        sv=SiSU_Env::InfoVersion.instance.get_version
+        if @env.output_dir_structure.by? == :language
+          home_pth='../..'
+          output_structure_by='(output organised by language & filetype)'
+        elsif @env.output_dir_structure.by? == :filetype
+          home_pth='..'
+          output_structure_by='(output organised by filetype)'
+        elsif @env.output_dir_structure.by? == :filename
+          home_pth='.'
+          output_structure_by='(output organised by filename)'
+        else
+          home_pth='.'
+          output_structure_by='(output organised by ?)'
+        end
+        <
+
+
+ 
+SiSU Metadata Harvest - Topics 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+
+
+ 
+ 
+ 
+SiSU Metadata Harvest - Topics #{output_structure_by} 
+[ HOME  ] also see SiSU Metadata Harvest - Authors 
+#{@env.widget_static.search_form}
+ 
+#{harvest_languages}
+ 
+WOK
+      end
+      def html_head
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] \
+          << html_head_adjust(lng,'maintenance') \
+            if @opt.act[:maintenance][:set]==:on
+          @output[lng][:html] << html_head_adjust(lng)
+        end
+      end
+      def html_alph
+        a=[]
+        a << ''
+        @alph.each do |x|
+          a << ((x =~/[0-9]/) \
+          ? ''
+          : %{#{x} , })
+        end
+        a=a.join
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] << a \
+            if @opt.act[:maintenance][:set]==:on
+          @output[lng][:html] << a
+        end
+      end
+      def html_tail
+        a =< 
+ 
+ 
+ 
+ 
+ 
+ 
+#{SiSU_Proj_HTML::Bits.new.credits_sisu}
+
+
+WOK
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] << a \
+            if @output[lng][:html_mnt].is_a?(File)
+          @output[lng][:html] << a
+        end
+      end
+      def do_html(lng,html)
+        @output[lng][:html] << html
+      end
+      def do_html_maintenance(lng,html)
+        @output[lng][:html_mnt] << html \
+          if @output[lng][:html_mnt].is_a?(File)
+      end
+      def do_string(lng,attrib,string)
+        html=%{
#{string}
}
+        do_html(lng,html)
+        do_html_maintenance(lng,html) \
+          if @output[lng][:html_mnt].is_a?(File)
+      end
+      def do_string_default(lng,attrib,string)
+        html=%{#{string}
}
+        do_html(lng,html)
+      end
+      def do_string_maintenance(lng,attrib,string)
+        html=%{#{string}
}
+        do_html_maintenance(lng,html) \
+          if @output[lng][:html_mnt].is_a?(File)
+      end
+      def do_string_name(lng,attrib,string)
+        f=/^(\S)/.match(string)[1]
+        if @lng != lng
+          @alph=@alphabet_list.dup
+          @letter=@alph.shift
+          @lng = lng
+        end
+        if @letter < f
+          while @letter < f
+            if @alph.length > 0
+              @letter=@alph.shift
+              if @output[lng][:html_mnt].is_a?(File)
+                @output[lng][:html_mnt] \
+                << %{\n#{@letter} 
}
+              end
+              @output[lng][:html] \
+              << %{\n#{@letter} 
}
+            else break
+            end
+          end
+        end
+        name=string.strip.gsub(/\s+/,'_')
+        html=%{#{string} 
}
+        do_html(lng,html)
+        do_html_maintenance(lng,html) \
+          if @output[lng][:html_mnt].is_a?(File)
+      end
+      def do_array(lng,lv,array)
+        lv+=1
+        array.each do |b|
+          do_case(lng,lv,b)
+        end
+      end
+      def do_hash_md(lng,attrib,hash)
+        lang_code_insert=SiSU_Env::FilenameLanguageCodeInsert.new(@opt,lng).language_code_insert
+        manifest_at=if @env.output_dir_structure.by? == :language
+          hash[:file] + Sfx[:html]
+        elsif @env.output_dir_structure.by? == :filetype
+          hash[:file] + lang_code_insert +  Sfx[:html]
+        elsif @env.output_dir_structure.by? == :filename
+          "./#{hash[:file]}/#{hash[:page]}"
+        else '' #error
+        end
+        html=%{#{hash[:title]}  - #{hash[:author]}}
+        do_string_default(lng,attrib,html)
+      end
+      def do_hash_md_maintenance(lng,attrib,hash)
+        if @output[lng][:html_mnt].is_a?(File) #should not be run for presentation output
+          html=%{[src ]  #{hash[:title]}  - #{hash[:author]}}
+          do_string_maintenance(lng,attrib,html)
+        end
+      end
+      def do_hash(lng,lv,hash)
+        lv+=1
+        key=[]
+        hash.each_key do |m|
+          if m == :md
+            do_case(lng,lv,hash[m])
+          elsif m != :title \
+          and m != :author \
+          and m != :filename \
+          and m != :file \
+          and m != :rough_idx \
+          and m != :page
+            key << m
+          elsif m == :title
+            do_hash_md(lng,'work',hash)
+            do_hash_md_maintenance(lng,'work',hash)
+          end
+        end
+        if key.length > 0
+          key.sort.each do |m|
+            attrib="lev#{lv}"
+            lv==0 ? do_string_name(lng,attrib,m) : do_string(lng,attrib,m)
+            do_case(lng,lv,hash[m])
+          end
+        end
+      end
+      def do_case(lng,lv,a)
+        case a
+        when String
+          attrib="lev#{lv}"
+          if a=~/S/
+            lv==0 ? do_string_name(lng,attrib,a) : do_string(lng,attrib,a)
+          end
+        when Array
+          do_array(lng,lv,a)
+        when Hash
+          do_hash(lng,lv,a)
+        end
+      end
+      #def html_body
+      #  the_idx=@the_idx
+      #  the_idx.each_pair do |lng,lng_array|
+      #    lng_array.sort.each do |a|
+      #      do_case(lng,-1,a)
+      #    end
+      #  end
+      #end
+      self
+    end
+  end
+end
+__END__
+terms -|_  t{tl1} -|_ {fa}[fa]{filenames and other details}
+       |           |_ {tl2} -|_ {fa}[fa]{filenames and other details}
+       |           |         |_{tl3} -|_ {fa}[fa]{filenames and other details}
+       |           |         |        |_{tl4} - {fa}[fa]{filenames and other details}
+       |           |         |        |
+       |           |         |        |_{tl4a} - {fa}[fa]{filenames and other details}
+       |           |         |        |
+       |           |         |        |_{tl4b} - {fa}[fa]{filenames and other details}
+       |           |         |        |
+       |           |         |        |_ ...
+       |           |         |
+       |           |         |_{tl3a} - {fa}[fa]{filenames and other details}
+       |           |
+       |           |_{tl2a} - {fa}[fa]{filenames and other details}
+       |
+       |_ t{tl1a} -|_ {fa}[fa]{filenames and other details}
+                   |_ ...
+#+END_SRC
+
+** authors
+*** html_harvest_authors.rb
+
+#+BEGIN_SRC ruby  :tangle "../lib/sisu/html_harvest_authors.rb"
+# <>
+module SiSU_HarvestAuthors
+  require_relative 'html_harvest_author_format'          # html_harvest_author_format.rb
+  require_relative 'html_parts'                          # html_parts.rb
+  class Songsheet
+    @@the_idx_authors={}
+    def initialize(opt,env)
+      @opt,@env=opt,env
+      @file_list=opt.files
+    end
+    def songsheet
+      idx_array={}
+      @opt.f_pths.each do |y|
+        lang_hash_file_array={}
+        name=y[:f]
+        filename=y[:pth] + '/' + y[:f]
+        File.open(filename,'r') do |file|
+          file.each_line("\n\n") do |line|
+            if line =~/^@(?:title|creator|date):(?:\s|$)/m
+              lang_hash_file_array[y[:lng_is]] ||= []
+              lang_hash_file_array[y[:lng_is]] << line
+            elsif line =~/^@\S+?:(?:\s|$)/m \
+            or line =~/^(?:\s*\n|%+ )/
+            else break
+            end
+          end
+        end
+        lang_hash_file_array.each_pair do |lang,a|
+          idx_array[lang] ||= []
+          idx_array=SiSU_HarvestAuthors::Harvest.new(
+            @opt,
+            @env,
+            a,
+            filename,
+            name,
+            idx_array,
+            lang
+          ).extract_harvest
+        end
+      end
+      the_idx=SiSU_HarvestAuthors::Index.new(
+        idx_array,
+        @@the_idx_authors
+      ).construct_book_author_index
+      SiSU_HarvestAuthors::OutputIndex.new(
+        @opt,
+        the_idx
+      ).html_print.html_songsheet
+    end
+  end
+  class Harvest
+    def initialize(opt,env,data,filename,name,idx_array,lang)
+      @opt, @env,@data,@filename,@name,@idx_array,@lang=
+        opt,env, data, filename, name, idx_array, lang
+    end
+    def extract_harvest
+      data,   filename, name, idx_array, lang =
+        @data,@filename,@name,@idx_array,@lang
+      @title=@subtitle=@fulltitle=@author=@author_format=@date=nil
+      @authors=[]
+      rgx={}
+      rgx[:author]=/^@creator:(?:[ ]+|.+?:author:[ ]+)(.+?)(?:\||\n)/m
+      rgx[:title]=/^@title:[ ]+(.+)/
+      rgx[:subtitle]=/^@title:.+?:subtitle:[ ]+(.+?)\n/m
+      rgx[:date]=/^@date:(?:[ ]+|.+?:published:[ ]+)(\d{4})/m
+      data.each do |para|
+        if para=~ rgx[:title]
+          @title=rgx[:title].match(para)[1]
+        end
+        if para=~ rgx[:subtitle]
+          @subtitle=rgx[:subtitle].match(para)[1]
+        end
+        if para=~ rgx[:author]
+          @author_format=rgx[:author].match(para)[1]
+        end
+        if para=~ rgx[:date]
+          @date=rgx[:date].match(para)[1]
+        end
+        break if @title && @subtitle && @author && @date
+      end
+      @fulltitle=@subtitle \
+      ? (@title + ' - ' + @subtitle)
+      : @title
+      if @title \
+      and @author_format
+        creator=SiSU_FormatAuthor::Author.new(@author_format.strip).author_details
+        @authors,@authorship=creator[:authors],creator[:authorship]
+        file=if name=~/~[a-z]{2,3}\.ss[mt]$/
+          name.sub(/~[a-z]{2,3}\.ss[mt]$/,'')
+        else
+          name.sub(/\.ss[mt]$/,'')
+        end
+        page=if @env.output_dir_structure.by? == :language
+          "#{lang}/sisu_manifest.html"
+        else
+          "sisu_manifest.#{lang}.html"
+        end
+        idx_array[lang] <<= {
+          filename: filename,
+          file: file,
+          date: @date,
+          title: @fulltitle,
+          author: creator,
+          page: page,
+          lang: lang
+        }
+      else
+        #p "missing author field: #{@filename} title: #{@title}; author: #{@author_format}"
+      end
+      idx_array[lang]=idx_array[lang].flatten
+      idx_array
+    end
+  end
+  class Index
+    def initialize(idx_array,the_idx)
+      @idx_array,@the_idx=idx_array,the_idx
+      @@the_idx_authors=@the_idx
+    end
+    def capital(txt)
+      txt[0].chr.capitalize + txt[1,txt.length]
+    end
+    def construct_book_author_index
+      idx_array=@idx_array
+      idx_array.each_pair do |lang,idx_arr|
+        @@the_idx_authors[lang] ||= {}
+        idx_arr.each do |idx|
+          idx[:author][:last_first_format_a].each do |author|
+            author=author.strip
+            if @@the_idx_authors[lang][author].is_a?(NilClass)
+              @@the_idx_authors[lang][author]={ md: [] }
+            end
+            @@the_idx_authors[lang][author][:md] << {
+              filename: idx[:filename],
+              file: idx[:file],
+              author: idx[:author],
+              title: idx[:title],
+              date: idx[:date],
+              page: idx[:page],
+              lang: idx[:lang]
+            }
+          end
+        end
+      end
+      @the_idx=@@the_idx_authors
+    end
+  end
+  class OutputIndex
+    require_relative 'i18n'                               # i18n.rb
+    def initialize(opt,the_idx)
+      @opt,@the_idx=opt,the_idx
+      @env=SiSU_Env::InfoEnv.new
+      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
+      @alphabet_list=%W[9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
+      @alph=@alphabet_list.dup
+      @letter=@alph.shift
+    end
+    def html_file_open
+      @the_idx.keys.each do |lng|
+        @output ||={}
+        @output[lng] ||={}
+        harvest_pth,file='',''
+        if @env.output_dir_structure.by? == :language
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub + '/' \
+          + lng + '/' \
+          + 'manifest'
+          file="#{harvest_pth}/authors.html"
+        elsif @env.output_dir_structure.by? == :filetype
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub + '/' \
+          + 'manifest'
+          file="#{harvest_pth}/authors.#{lng}.html"
+        elsif @env.output_dir_structure.by? == :filename
+          harvest_pth=@env.path.webserv + '/' \
+          + @opt.base_stub
+          file="#{harvest_pth}/authors.#{lng}.html"
+        end
+        FileUtils::mkdir_p(harvest_pth) \
+          unless FileTest.directory?(harvest_pth)
+        fileinfo=(@opt.act[:verbose][:set]==:on \
+        || @opt.act[:verbose_plus][:set]==:on \
+        || @opt.act[:urls_selected][:set]==:on \
+        || @opt.act[:maintenance][:set]==:on) \
+        ? ("file://#{file}") : ''
+        SiSU_Screen::Ansi.new(
+          @opt.act[:color_state][:set],
+          "harvest authors (#{@opt.files.length} files)",
+          fileinfo
+        ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
+        @output[lng][:html]=File.new(file,'w')
+      end
+    end
+    def html_file_close
+      @the_idx.keys.each do |lng|
+        @output[lng][:html].close
+        @output[lng][:html_mnt].close \
+          if @output[lng][:html_mnt].is_a?(File)
+      end
+    end
+    def html_print
+      def html_songsheet
+        html_file_open
+        html_head
+        html_alph
+        html_body
+        html_tail
+        html_file_close
+      end
+      def html_head_adjust(lng,type='')
+        css_path,topics='',''
+        if @env.output_dir_structure.by? == :language
+          css_path=(type !~/maintenance/) \
+          ? '../../_sisu/css/harvest.css'
+          : 'harvest.css'
+          topics='topics.html'
+        elsif @env.output_dir_structure.by? == :filetype
+          css_path=(type !~/maintenance/) \
+          ? '../_sisu/css/harvest.css'
+          : 'harvest.css'
+          topics="topics.#{lng}.html"
+        elsif @env.output_dir_structure.by? == :filename
+          css_path=(type !~/maintenance/) \
+          ? './_sisu/css/harvest.css'
+          : 'harvest.css'
+          topics="topics.#{lng}.html"
+        end
+        ln=SiSU_i18n::Languages.new.language.list
+        harvest_languages=''
+        @the_idx.keys.each do |lg|
+          if @env.output_dir_structure.by? == :language
+            harvest_pth="../../#{lg}/manifest"
+            file="#{harvest_pth}/authors.html"
+          elsif @env.output_dir_structure.by? == :filetype
+            harvest_pth='.'
+            file="#{harvest_pth}/authors.#{lg}.html"
+          elsif @env.output_dir_structure.by? == :filename
+            harvest_pth='.'
+            file="#{harvest_pth}/authors.#{lg}.html"
+          end
+          l=ln[lg][:t]
+          harvest_languages +=
+            %{#{l}    }
+        end
+        sv=SiSU_Env::InfoVersion.instance.get_version
+        if @env.output_dir_structure.by? == :language
+          home_pth='../..'
+          output_structure_by=
+            '(output organised by language & filetype)'
+        elsif @env.output_dir_structure.by? == :filetype
+          home_pth='..'
+          output_structure_by=
+            '(output organised by filetype)'
+        elsif @env.output_dir_structure.by? == :filename
+          home_pth='.'
+          output_structure_by=
+            '(output organised by filename)'
+        else
+          home_pth='.'
+          output_structure_by='(output organised by ?)'
+        end
+        <
+
+
+ 
+SiSU Metadata Harvest - Authors 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+
+
+ 
+ 
+ 
+SiSU Metadata Harvest - Authors #{output_structure_by} 
+[ HOME  ] also see SiSU Metadata Harvest - Topics 
+#{@env.widget_static.search_form}
+ 
+#{harvest_languages}
+ 
+WOK
+      end
+      def html_head
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] \
+          << html_head_adjust(lng,'maintenance') \
+            if @opt.act[:maintenance][:set]==:on
+          @output[lng][:html] \
+          << html_head_adjust(lng)
+        end
+      end
+      def html_alph
+        a=[]
+        a << ''
+        @alph.each do |x|
+          a << ((x =~/[0-9]/) \
+          ? ''
+          : %{#{x} , })
+        end
+        a=a.join
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] << a \
+            if @opt.act[:maintenance][:set]==:on
+          @output[lng][:html] << a
+        end
+      end
+      def html_tail
+        a =< 
+ 
+ 
+ 
+ 
+ 
+ 
+#{SiSU_Proj_HTML::Bits.new.credits_sisu}
+
+
+WOK
+        @the_idx.keys.each do |lng|
+          @output[lng][:html_mnt] << a \
+            if @output[lng][:html_mnt].is_a?(File)
+          @output[lng][:html] << a
+        end
+      end
+      def do_html(lng,html)
+        @output[lng][:html_mnt] << html \
+          if @output[lng][:html_mnt].is_a?(File)
+        @output[lng][:html] << html
+      end
+      def do_string_name(lng,attrib,string)
+        f=/^(\S)/.match(string[0])[1]
+        if @lng != lng
+          @alph=@alphabet_list.dup
+          @letter=@alph.shift
+          @lng = lng
+        end
+        if @letter < f
+          while @letter < f
+            if @alph.length > 0
+              @letter=@alph.shift
+              if @output[lng][:html_mnt].is_a?(File)
+                @output[lng][:html_mnt] \
+                << %{\n
#{@letter}