proc colors:open_cde_resourcefile { file } {
  global start_log

  set ans ""
  set ret [catch {open $file r} ans]
  if {$ret == 0} {
    lappend start_log " Opening $file"
    return $ans
  } else {
    lappend start_log "Error opening file: ($ans)"
    lappend start_log "Error: $ans"
    return ""
  }
}

proc colors:read_cde_palette { palf } {
  global start_log
  global colorglb
  global theme_system

  lappend start_log "Looking for $theme_system palette $palf"
  if {[file readable $palf]} {
    lappend "Opening palette $palf"
    if {![catch {open $palf r} fh]} {
      chan gets $fh activetitle   ;# active window borders; Colorset 2
      chan gets $fh inactivetitle ;# inactive window borders and default fg/bg/sh/hi, menus; Colorset 5
      chan gets $fh wkspc1  ;# Colorset 40,41
      chan gets $fh textbg  ;# text entry and list widgets; Colorset 20
      chan gets $fh guibg   ;#(*.background) - panels, default for tk under cde; Colorset 21
      chan gets $fh menubg  ;# transient windows, says NsCDE. Almost the same as guibg; Colorset 22,44,45
      chan gets $fh wkspc4  ;# Colorset 46,47
      chan gets $fh iconbg  ;#control panel bg too; not used by NsCDE
      catch {chan close $fh}
    }
  } else {
    lappend start_log "Failed to open file $palf"
    return 0
  }
          
  lappend start_log "CoLoR_guibg: $guibg"
  lappend start_log "CoLoR_textbg: $textbg"
  lappend start_log "CoLoR_menubg: $menubg"
  lappend start_log "CoLoR_iconbg: $iconbg"
  lappend start_log "CoLoR_activetitle: $activetitle"
  lappend start_log "CoLoR_inactivetitle: $inactivetitle"
  lappend start_log "CoLoR_wkspc1: $wkspc1"
  lappend start_log "CoLoR_wkspc4: $wkspc4"

  if {[info exists activetitle]} {
    set hlbg $activetitle
  } elseif {[info exists wkspc4]} {
    set hlbg $wkspc4
  } else {
    set hlbg "#b24d7a"
  }
  
  lassign [colors:shades $colorglb(bg)] panelbg thumb lighter light shadow
  set colorglb(canvbg) $panelbg
  set colorglb(treebg) $panelbg
  set colorglb(thumb) $thumb
  set colorglb(trough) $shadow
  set colorglb(lighter) $lighter
  set colorglb(light) $light
  set colorglb(shadow) $shadow

  # In NsCDE, we get bg, fg, textbg, and textfg from the local configfile.
  # In plain CDE, we set it to what we got from the palette.
  if {$theme_system eq "CDE"} {
    set colorglb(textbg) $textbg
  }
  set colorglb(menubg) $menubg
  set colorglb(hlbg) $hlbg
  # CDE, in both implementations, is unreliable at specifying contrasting
  # foreground
  set colorglb(fg) [colors:contrast $colorglb(bg)]
  set colorglb(menufg) [colors:contrast $menubg]
  set colorglb(textfg) [colors:contrast $textbg]
  set colorglb(hlfg) [colors:contrast $hlbg]
  set colorglb(canvfg) [colors:contrast $colorglb(shadow)]
  set colorglb(treefg) $colorglb(canvfg)

  return 1
}

proc colors:get_cde_params { } {
  global cvscfg
  global colorglb
  global start_log
  global theme_system
  global env
  
  # NsCDE looks like CDE, but it's really mostly FVWM. The current palette and
  # colorsets are listed in FVWM_USERDIR/Colorset.fvwmgen (usualy
  # ~/.NsCDE/Colorset.fvwmgen) The palettes are in /usr/share/NsCDE/palettes
  # but env(NSCDE_PALETTE) gets reset. Maybe it's best to get the colors from
  # there too?
  if {[info exists env(XDG_CURRENT_DESKTOP)] && $env(XDG_CURRENT_DESKTOP) eq "NsCDE"} {
    set configfile "$env(FVWM_USERDIR)/Colorset.fvwmgen"
    set theme_system "NsCDE"
    lappend start_log "Look for $configfile"
    if {[file readable $configfile]} {
      lappend start_log "Opening $configfile"
      if {![catch {open $configfile r} fh]} {
        while {[chan gets $fh ln] != -1} {
          if {[string match {SetEnv NSCDE_PALETTE *} $ln]} {
            set palf [lindex $ln 2]
            set palette [file join / usr share NsCDE palettes $palf.dp]
            lappend start_log "Using palette $palf"
          } elseif  {[string match {Colorset 20*} $ln]} {
             set textfg [string trimright [lindex $ln 3] ","]
             set textbg [string trimright [lindex $ln 5] ","]
          } elseif  {[string match {Colorset 21*} $ln]} {
             set fg [string trimright [lindex $ln 3] ","]
             set bg [string trimright [lindex $ln 5] ","]
          }
        }

        catch {chan close $fh}
        set colorglb(bg) $bg
        set colorglb(fg) $fg
        set colorglb(textbg) $textbg
        set colorglb(textfg) $textfg
        set colorglb(treefg) $fg
        set colorglb(canvfg) $fg

        lassign [colors:shades $bg] panelbg thumb lighter light shadow
        set colorglb(canvbg) $panelbg
        set colorglb(treebg) $panelbg
        set colorglb(thumb) $thumb
        set colorglb(trough) $shadow
        set colorglb(lighter) $lighter
        set colorglb(light) $light
        set colorglb(shadow) $shadow

        lappend start_log "CoLoR_bg: $bg"
        lappend start_log "CoLoR_fg: $fg"
        lappend start_log "CoLoR_textbg: $textbg"
        lappend start_log "CoLoR_textfg: $textfg"
      }
    } else {
      lappend start_log "Failed to read $configfile"
      return 0
    }
    if {[string length $palf]} {
      colors:read_cde_palette $palette
    }
    set guifont TkDefaultFont
    #set guifont {{Serif} 10}
    set txtfont TkFixedFont
    set listfont TkDefaultFont
    set menufont {{DejaVu Serif} 10}
    set btnfont {{DejaVu Serif} 10}
    set dlgfont TkHeadingFont

    set colorglb(guifont) $guifont
    set colorglb(btnfont) $guifont
    set colorglb(textfont) $txtfont
    set colorglb(menufont) $menufont
    set colorglb(btnfont) $btnfont
    set colorglb(dialogfont) $dlgfont
    set colorglb(listboxfont) $guifont

    return 1
  } else {
    if {! [info exists env(DTUSERSESSION)] } {
      lappend start_log "DTUSERSESSION not set. Not in CDE"
      return 0
    }
    set theme_system "CDE"

    set guifont TkDefaultFont
    set listfont TkFixedFont
    set txtfont TkFixedFont
    set menufont "Serif"
    set btnfont "Serif"
    set dlgfont TkHeadingFont

    set colorglb(guifont) $guifont
    set colorglb(textfont) $txtfont
    set colorglb(menufont) $menufont
    set colorglb(btnfont) $btnfont
    set colorglb(dialogfont) $dlgfont
    set colorglb(listboxfont) $listfont
  
    # Nothing really tells us this, but tk gets it
    set bg [option get . background background]
    lappend start_log "CoLoR_bg: $bg"
    # CDE
    lassign [colors:shades $bg] panelbg thumb lighter light shadow
    set colorglb(canvbg) $panelbg
    set colorglb(treebg) $panelbg
    set colorglb(thumb) $thumb
    set colorglb(trough) $shadow
    set colorglb(lighter) $lighter
    set colorglb(light) $light
    set colorglb(shadow) $shadow

    set colorglb(bg) $bg
    # Tk gets a foreground, but it's usually wrong. Use its default though.
    set fg [option get . foreground foreground]
    set colorglb(fg) $fg

    # If we can find the user's dt.resources file, we can find out the
    # palette and background/foreground colors
    set fh ""
    set palette ""
    set cur_rsrc [file join $cvscfg(home) .dt/sessions/current/dt.resources]
    set hom_rsrc [file join $cvscfg(home) .dt/sessions/home/dt.resources]
    if {[file readable $cur_rsrc] && [file readable $hom_rsrc]} {
      # Both exist.  Use whichever is newer
      if {[file mtime $cur_rsrc] > [file mtime $hom_rsrc]} {
        lappend start_log "  $cur_rsrc is newer"
        set fh [colors:open_cde_resourcefile $cur_rsrc]
        if {$fh == ""} {
          set fh [colors:open_cde_resourcefile $hom_rsrc]
        }
      } else {
        lappend start_log "  $hom_rsrc is newer"
        set fh [colors:open_cde_resourcefile $hom_rsrc]
        if {$fh == ""} {
          set fh [colors:open_cde_resourcefile $cur_rsrc]
        }
      }
    } elseif {[file readable $cur_rsrc]} {
      # Otherwise try current first
      set fh [colors:open_cde_resourcefile $cur_rsrc]
      if {$fh == ""} {
        set fh [colors:open_cde_resourcefile $hom_rsrc]
      }
    } elseif {[file readable $hom_rsrc]} {
      set fh [colors:open_cde_resourcefile $hom_rsrc]
    }
    if {[string length $fh]} {
      set palf ""
      while {[chan gets $fh ln] != -1} {
        regexp {^\*background:[ \t]*(.*)$} $ln nil bg
        regexp {^\*foreground:[ \t]*(.*)$} $ln nil fg
        regexp {^\*0\*ColorPalette:[ \t]*(.*)$} $ln nil palette
        regexp {^Window.Color.Background:[ \t]*(.*)$} $ln nil bg
        regexp {^Window.Color.Foreground:[ \t]*(.*)$} $ln nil fg
      }
      catch {chan close $fh}
      lappend start_log "CoLoR_bg: $bg"
      lappend start_log "CoLoR_fg: $fg"
      #
      # If the *0*ColorPalette setting was found above, try to find the
      # indicated file in ~/.dt, $DTHOME, or /usr/dt.
      #
      if {[string length $palette]} {
        foreach dtdir {/usr/dt /etc/dt [file join $cvscfg(home) .dt]} {
          # This uses the last palette that we find
          if {[file readable [file join $dtdir palettes $palette]]} {
            set palf [file join $dtdir palettes $palette]
          }
        }
        if {[string length $palf]} {
          colors:read_cde_palette $palf
        }
      }
    } else {
      lappend start_log "Neither [file join $cvscfg(home) .dt/sessions/current/dt.resources] nor"
      lappend start_log "        [file join $cvscfg(home) .dt/sessions/home/dt.resources] was readable"
      lappend start_log "   Falling back to plain X11"
      return 0
    }
  
    # Relief like CDE menu
    option add *Menu.borderWidth 1
    # This makes it look like the native CDE checkbox
    option add *Checkbutton.offRelief sunken
    return 1
  }
}

proc colors:get_gtk_theme { } {
  global cvscfg
  global colorglb
  global env
  global start_log

  lappend start_log "Looking for a GTK theme"

  switch -glob $env(XDG_CURRENT_DESKTOP) {
    {*GNOME} -
    {*XFCE} {
      set ret [catch {exec {*}gsettings get org.gnome.desktop.interface gtk-theme} theme]
      set ret [catch {exec {*}gsettings get org.gnome.desktop.interface font-name} menufont]
    }
    {*MATE} {
      set ret [catch {exec {*}gsettings get org.mate.interface gtk-theme} theme]
    }
    {*COSMIC} {
      set ret [catch {exec {*}gsettings get org.gnome.desktop.interface gtk-theme} theme]
    }
    {*KDE} {
      # This doesn't have the current color scheme but start with it
      set ret [catch {exec {*}gsettings get org.gnome.desktop.interface gtk-theme} theme]
      # font comes back in a bad format
      set ret [catch {exec {*}gsettings get org.gnome.desktop.interface font-name} menufont]
    }
  }
 
  if {[info exists theme]} {
    set theme [string trim $theme "'"]
    lappend start_log "THEME $theme"
    # Look for the theme file ~/.themes/$theme or /usr/share/themes/$theme
    set localthemedir [file join $cvscfg(home) .themes $theme]
    set systhemedir [file join / usr share themes $theme]
    lappend start_log " Look for $localthemedir"
    lappend start_log " Look for $systhemedir"
    if {[file isdirectory $localthemedir]} {
      set themedir $localthemedir
    } elseif {[file isdirectory $systhemedir]} {
      set themedir $systhemedir
    }
    # $theme/$QT_QPA_PLATFORMTHEME/gtkrc  gtk-color-scheme lines
    if { [info exists themedir] } {
      lappend start_log " Found directory $themedir"
      # older gtk2 themes use gtkrc
      lappend start_log " Look for $themedir/gtk-2.0/gtkrc"
      if {[file readable $themedir/gtk-2.0/gtkrc]} {
        lappend start_log " Found $themedir/gtk-2.0/gtkrc"
        set theme_rc "$themedir/gtk-2.0/gtkrc"
        lappend start_log " Opening $theme_rc"
        set gtkcolorscheme ""
        if {![catch {open $theme_rc r} th]} {
          while {[chan gets $th ln] != -1} {
            if {[string match "gtk?color?scheme*" $ln]} {
              # grab what's inside the quotes
              regexp {\"(.*?)\"} $ln all inside
              # remove spaces if present
              regsub -all { } $inside {} ln
              regsub -all {\\n} $ln {^} ln
              append ln "^"
              append gtkcolorscheme $ln
            }
          }
          catch {chan close $th}
        } else {
          lappend start_log " Open file failed"
        }
      
        if {[info exists gtkcolorscheme]} {
          regsub -all {\\n} $gtkcolorscheme {^} gtkcolorscheme
          foreach entry [split $gtkcolorscheme "^"] {
            set entry [string trimright $entry]
            set fields [split $entry {:}]
            set cname [lindex $fields 0]
            set cval [lindex $fields 1]
            lappend start_log "CoLoR_$cname: $cval"
            switch -exact -- $cname {
              # Fill in the variables, though some may be overridden
              {bg_color} {set bg $cval}
              {fg_color} {set fg $cval}
              {base_color} {set textbg $cval}
              {text_color} {set textfg $cval}
              {selected_bg_color} {set hlbg $cval}
              {selected_fg_color} {set hlfg $cval}
              {tooltip_bg_color} {set tooltipbg $cval}
              {tooltip_fg_color} {set tooltipfg $cval}
              {menu_bg} {set menubg $cval}
              {menu_fg} {set menufg $cval}
              {link_color} {set linkfg $cval}
            }
          }
          if {! [info exists bg] || ! [info exists fg]} {
            lappend start_log " No topelevel fg and bg from gtkrc"

            # Try to find a gtk3 css file
            lappend start_log " Look for $themedir/gtk-3.0/gtk-main.css"
            if {[file readable $themedir/gtk-3.0/gtk-main.css]} {
              lappend start_log " Found $themedir/gtk-3.0/gtk-main.css"
              set theme_rc "$themedir/gtk-3.0/gtk-main.css"
              if { [info exists theme_rc] } {
                lappend start_log " Opening $theme_rc"
                if {![catch {open $theme_rc r} th]} {
                  while {[chan gets $th ln] != -1} {
                    if {[string match "@define-color bg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all bg
                    } elseif {[string match "@define-color fg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all fg
                    } elseif {[string match "@define-color base_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all textbg
                    } elseif {[string match "@define-color text_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all textfg
                    } elseif {[string match "@define-color selected_bg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all hlbg
                    } elseif {[string match "@define-color selected_fg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all hlfg
                    } elseif {[string match "@define-color tooltip_bg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all tooltipbg
                    } elseif {[string match "@define-color tooltip_fg_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all tooltipfg
                    } elseif {[string match "@define-color link_color *" $ln]} {
                      regexp {.*lor (#\w+);} $ln all linkfg
                    }
                  }
                  catch {chan close $th}
                } else {
                  lappend start_log " Open file failed"
                }
              } else {
                lappend start_log " $theme_rc not found"
              }
            }
            if {! [info exists bg] || ! [info exists fg]} {
              lappend start_log " No topelevel fg and bg from gtk-main.css"
              return 0
            }
          }
          set colorglb(bg) $bg
          set colorglb(fg) $fg
          # GTK
          lassign [colors:shades $colorglb(bg)] panelbg thumb lighter light shadow
          set colorglb(canvbg) $panelbg
          set colorglb(treebg) $panelbg
          set colorglb(thumb) $thumb
          set colorglb(trough) $shadow
          set colorglb(lighter) $lighter
          set colorglb(light) $light
          set colorglb(shadow) $shadow
        }

        # KDE is still GTK, but the current colors are in a different file
        if {[string match "*KDE" $env(XDG_CURRENT_DESKTOP)]} {
          # ~/.config/kdeglobals contains the current colors
          set kdeglobal_rc [file join $cvscfg(home) .config kdeglobals]
          lappend start_log "Look for file $kdeglobal_rc"
          if {[file readable $kdeglobal_rc]} {
            lappend start_log " Opening $kdeglobal_rc"
            if {![catch {open $kdeglobal_rc r} kh]} {
              while {[chan gets $kh ln] != -1} {
                if {[string match {\[Colors:Tooltip\]} $ln]} {
                  lappend start_log " Colors:Tooltip"
                  while {[chan gets $kh ln] != -1} {
                    if {$ln eq ""} {break}
                    set fields [split $ln {=}]
                    set f0 [lindex $fields 0]
                    set f1 [lindex $fields 1]
                    switch -exact -- $f0 {
                      {BackgroundNormal} {
                        set tooltipbg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_BackgroundNormal: $tooltipbg"
                      }
                      {ForegroundNormal} {
                        set tooltipfg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_ForegroundNormal: $tooltipfg"
                      } 
                    }
                  }
                } elseif {[string match {\[Colors:Window\]} $ln]} {
                  lappend start_log " Colors:Window"
                  while {[chan gets $kh ln] != -1} {
                    if {$ln eq ""} {break}
                    set fields [split $ln {=}]
                    set f0 [lindex $fields 0]
                    set f1 [lindex $fields 1]
                    switch -exact -- $f0 {
                      {BackgroundNormal} {
                        set bg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_BackgroundNormal: $bg"
                      }
                      {ForegroundNormal} {
                        set fg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_ForegroundNormal: $fg"
                      } 
                    }
                  } 
                } elseif {[string match {\[Colors:View\]} $ln]} {
                  lappend start_log " Colors:View"
                  while {[chan gets $kh ln] != -1} {
                    if {$ln eq ""} {break}
                    set fields [split $ln {=}]
                    set f0 [lindex $fields 0]
                    set f1 [lindex $fields 1]
                    switch -exact -- $f0 {
                      {BackgroundNormal} {
                        set textbg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_BackgroundNormal: $textbg"
                      }
                      {ForegroundNormal} {
                        set textfg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_ForegroundNormal: $textfg"
                      } 
                    }
                  } 
                } elseif {[string match {\[Colors:Selection\]} $ln]} {
                  lappend start_log " Colors:Selection"
                  while {[chan gets $kh ln] != -1} {
                    if {$ln eq ""} {break}
                    set fields [split $ln {=}]
                    set f0 [lindex $fields 0]
                    set f1 [lindex $fields 1]
                    switch -exact -- $f0 {
                      {BackgroundNormal} {
                        set hlbg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_BackgroundNormal: $hlbg"
                      }
                      {ForegroundNormal} {
                        set hlfg [colors:rgb2hex $f1]
                        lappend start_log "CoLoR_ForegroundNormal: $hlfg"
                      } 
                    }
                  } 
                } elseif {[string match {ColorScheme=*} $ln]} {
                  set fields [split $ln {=}]
                  set kde_scheme [lindex $fields 1]
                }
              }
              catch {chan close $kh}
            } else {
              lappend start_log " Open file failed"
            }
            if {[info exists kde_scheme ]} {
              lappend start_log " ColorScheme $kde_scheme"
            }
          }
          # KDE
          lassign [colors:shades $bg] panelbg thumb lighter light shadow
          set colorglb(canvbg) $panelbg
          set colorglb(treebg) $panelbg
          set colorglb(thumb) $thumb
          set colorglb(trough) $shadow
          set colorglb(lighter) $lighter
          set colorglb(light) $light
          set colorglb(shadow) $shadow
        }
        set colorglb(bg) $bg
        set colorglb(fg) $fg
        if {[info exists hlbg]} {set colorglb(hlbg) $hlbg}
        if {[info exists hlfg]} {set colorglb(hlfg) $hlfg}
        if {[info exists textbg]} {set colorglb(textbg) $textbg}
        if {[info exists textfg]} {set colorglb(textfg) $textfg}
        if {[info exists trough]} {set colorglb(trough) $trough}
        if {[info exists tooltipbg]} {set colorglb(tooltipbg) $tooltipbg}
        if {[info exists tooltipfg]} {set colorglb(tooltipfg) $tooltipfg}
        if {[info exists linkfg]} {set colorglb(linkfg) $linkfg}
        set colorglb(canvfg) [colors:contrast $colorglb(canvbg)]
        set colorglb(treefg) $colorglb(canvfg)

        if {[info exists menufont]} {
          set colorglb(menufont) [colors:sanitize_fontspec $menufont]
          lappend start_log "FoNt_interface_font: $colorglb(menufont)"
        }
      }
    } else {
      lappend start_log " Theme gtkrc not found"
      return 0
    }
  } else {
    lappend start_log "Theme not detected"
    return 0
  }
  # I guess we found something
  return 1
}

proc colors:get_x11_resources { } {
  global colorglb
  global start_log
  
  lappend start_log "Getting X11 resources"
  if {[auto_execok xrdb] eq ""} {
    lappend start_log " No xrdb results"
    return 0
  }
  set pipe [open "|xrdb -q" r]
  lappend start_log "READING xrdb"
  while {[chan gets $pipe ln] > -1} {
    switch -glob -- $ln {
      {\*Toplevel.background:*} {
        set bg [lindex $ln 1]
        lappend start_log "CoLoR_Toplevel.background: $bg"
      }
      {\*Toplevel.foreground:*} {
        set fg [lindex $ln 1]
        lappend start_log "CoLoR_Toplevel.foreground: $fg"
      }
      {tkrev?background:*} {
        set bg [lindex $ln 1]
        lappend start_log "CoLoR_Toplevel.background: $bg"
      }
      {tkrev?foreground:*} {
        set fg [lindex $ln 1]
        lappend start_log "CoLoR_Toplevel.foreground: $fg"
      }
      {tkrev?Text.background:*} {
        set textbg [lindex $ln 1]
        lappend start_log "CoLoR_Text.background: $textbg"
      }
      {tkrev?Text.foreground:*} {
        set textfg [lindex $ln 1]
        lappend start_log "CoLoR_Text.foreground: $textfg"
      }
      {tkrev?Text.selectBackground:*} {
        set hlbg [lindex $ln 1]
        lappend start_log "CoLoR_Text.selectBackground: $hlbg"
      }
      {tkrev?Text.selectForeground:*} {
        set hlfg [lindex $ln 1]
        lappend start_log "CoLoR_Text.selectForeground: $hlfg"
      }
      {tkrev?Menu.background:*} {
        set menubg [lindex $ln 1]
        lappend start_log "CoLoR_Menu.background: $menubg"
      }
      {tkrev?Menu.foreground:*} {
        set menufg [lindex $ln 1]
        lappend start_log "CoLoR_Menu.foreground: $menufg"
      }
      {tkrev?Button.background:*} {
        set btnbg [lindex $ln 1]
        lappend start_log "CoLoR_Button.background: $btnbg"
      }
      {tkrev?Button.foreground:*} {
        set btnfg [lindex $ln 1]
        lappend start_log "CoLoR_Button.foreground: $btnfg"
      }
      {tkrev?Canvas.background:*} {
        set cvbg [lindex $ln 1]
        lappend start_log "CoLoR_Canvas.Background: $cvbg"
      }
      {tkrev?Canvas.foreground:*} {
        set cvfg [lindex $ln 1]
        lappend start_log "CoLoR_Canvas.Foreground: $cvfg"
      }
      {tkrev?Label.font:*} {
        set guifont [lindex $ln 1]
      }
      {tkrev?Menu.font:*} {
        set menufont [lindex $ln 1]
      }
      {tkrev?Button.font:*} {
        set btnfont [lindex $ln 1]
      }
      {tkrev?List.font:*} {
        set listboxfont [lindex $ln 1]
      }
      {tkrev?Text.font:*} {
        set textfont [lindex $ln 1]
      }
    }
  }
  catch {close $pipe}
  
  if {! [info exists bg] || ! [info exists fg]} {
    lappend start_log " xrdb doesn't provide toplevel fg and bg"
    return 0
  }
  
  set colorglb(bg) $bg
  set colorglb(fg) $fg

  # X11
  lassign [colors:shades $bg] panelbg thumb lighter light shadow
  set colorglb(canvbg) $panelbg
  set colorglb(treebg) $panelbg
  set colorglb(thumb) $thumb
  set colorglb(trough) $shadow
  set colorglb(lighter) $lighter
  set colorglb(light) $light
  set colorglb(shadow) $shadow
  
  if {[info exists menubg]} {set colorglb(menubg) $menubg} else {set colorglb(menubg) $bg}
  if {[info exists menufg]} {set colorglb(menufg) $menufg} else {set colorglb(menufg) $fg}
  if {[info exists btnbg]} {set colorglb(btnbg) $btnbg} else {set colorglb(btnbg) $bg}
  if {[info exists btnfg]} {set colorglb(btnfg) $btnfg} else {set colorglb(btnfg) $fg}
  if {[info exists textbg]} {set colorglb(textbg) $textbg} else {set colorglb(textbg) gray90}
  if {[info exists textfg]} {set colorglb(textfg) $textfg} else {set colorglb(textfg) black}
  if {[info exists cvbg]} {set colorglb(canvbg) $cvbg} else {set colorglb(canvbg) $colorglb(lighter)}
  if {[info exists cvfg]} {set colorglb(canvfg) $cvfg} else {set colorglb(canvfg) black}

  if {[info exists hlbg]} {set colorglb(hlbg) $hlbg} else {set colorglb(hlbg) "skyblue2"}
  if {$colorglb(hlbg) eq $bg} {set colorglb(hlbg) "#0092dc"}
  if {[info exists hlfg]} {set colorglb(hlfg) $hlfg} else {set colorglb(hlfg) "black"}

  set colorglb(treefg) $colorglb(canvfg)
  set colorglb(treebg) $colorglb(canvbg)

  if {[info exists guifont]} {
    set colorglb(guifont) [colors:sanitize_fontspec $guifont]
  }
  if {[info exists menufont]} {
    set colorglb(menufont) [colors:sanitize_fontspec $menufont]
  }
  if {[info exists btnfont]} {
    set colorglb(btnfont) [colors:sanitize_fontspec $btnfont]
  }
  if {[info exists listboxfont]} {
    set colorglb(listboxfont) [colors:sanitize_fontspec $listboxfont]
  }
  if {[info exists textfont]} {
    set colorglb(textfont) [colors:sanitize_fontspec $textfont]
  }

  return 1
}

# We picked out the colors from the DE. Now apply them.
proc colors:add_options {theme_system} {
  global colorglb
  global start_log

  lappend start_log "Theme system: $theme_system"

  catch {option add *Menu.font $colorglb(menufont)}
  catch {option add *Button.font $colorglb(btnfont)}
  catch {option add *Label.font $colorglb(guifont)}
  catch {option add *Entry.font $colorglb(guifont)}
  catch {option add *Text.font $colorglb(textfont)}

  if {! [info exists colorglb(bg)] } {
    puts "Variables not set. Something happened."
    return
  }

  if {! [info exists colorglb(menubg)] } { set colorglb(menubg) $colorglb(bg) }
  if {! [info exists colorglb(menufg)] } { set colorglb(menufg) $colorglb(fg) }
  if {! [info exists colorglb(btnbg)] } { set colorglb(btnbg) $colorglb(bg) }
  if {! [info exists colorglb(btnfg)] } { set colorglb(btnfg) $colorglb(fg) }

  # we really mean default. don't mess anything up.
  if {$theme_system eq "tk_default"} {return}

  option add *Background $colorglb(bg)
  option add *Foreground $colorglb(fg)
  option add *selectColor $colorglb(hlbg)
  option add *Menu.Background $colorglb(menubg)
  option add *Menu.Foreground $colorglb(menufg)
  option add *Menu.disabledForeground gray
  option add *Button.Background $colorglb(btnbg)
  option add *Button.Foreground $colorglb(btnfg)

  if {[string match {*CDE} $theme_system]} {
    option add *Button.activeBackground $colorglb(shadow)
    option add *Button.activeForeground $colorglb(fg)
    option add *Menu.activeBackground $colorglb(menubg)
    option add *Menu.activeForeground $colorglb(menufg)
    option add *Checkbutton.activeBackground $colorglb(bg)
    option add *Checkbutton.activeForeground $colorglb(fg)
  } else {
    option add *Button.activeBackground $colorglb(lighter)
    option add *Button.activeForeground $colorglb(fg)
    option add *Menu.activeBackground $colorglb(lighter)
    option add *Menu.activeForeground $colorglb(fg)
    # Prevent painted background from obscuring the checkmark
    option add *Checkbutton.selectColor ""
    option add *Radiobutton.selectColor ""
  }

  # Menu checkmarks
  option add *Menu.selectColor $colorglb(fg)

  option add *Canvas.Background $colorglb(canvbg)
  option add *Canvas.Foreground $colorglb(canvfg)
  option add *Dialog.Background $colorglb(menubg)
  option add *Dialog.Foreground $colorglb(menufg)

  option add *Entry.Background $colorglb(textbg)
  option add *Entry.Foreground $colorglb(textfg)
  option add *Entry.readonlyBackground $colorglb(light)
  option add *Entry.selectBackground $colorglb(hlbg)
  option add *Entry.selectForeground $colorglb(hlfg)

  option add *Listbox.background $colorglb(textbg)
  option add *Listbox.selectBackground $colorglb(hlbg)
  option add *Listbox.selectForeground $colorglb(hlfg)

  option add *Text.Background $colorglb(textbg)
  option add *Text.Foreground $colorglb(textfg)
}

# Takes hex color and makes some shades
proc colors:shades {bg} {
  global colorglb
  global start_log
  
  set rgb_bg [winfo rgb . $bg]
  set bg0 [expr [lindex $rgb_bg 0] / 256 ]
  set bg1 [expr [lindex $rgb_bg 1] / 256 ]
  set bg2 [expr [lindex $rgb_bg 2] / 256 ]

  # Approximation of perceived lightness
  set lightness [expr ( ((2*$bg0) + $bg1 + (3*$bg2)) / 6 )]
  lappend start_log "$bg lightness $lightness"
  
  # shadow
  set factor .85
  set shadow [format #%02x%02x%02x [expr int($factor * $bg0)] \
      [expr int($factor * $bg1)] \
      [expr int($factor * $bg2)]]
  
  set inv0 [expr 255 - $bg0]
  set inv1 [expr 255 - $bg1]
  set inv2 [expr 255 - $bg2]
  
  # light
  set factor .15
  set add0 [expr int($factor*$inv0)]
  set add1 [expr int($factor*$inv1)]
  set add2 [expr int($factor*$inv2)]
  
  set light [format #%02x%02x%02x [expr {$bg0 + $add0}] \
      [expr {$bg1 + $add1}] \
      [expr {$bg2 + $add2}]]
  
  # lighter
  set factor .3
  set add0 [expr int($factor*$inv0)]
  set add1 [expr int($factor*$inv1)]
  set add2 [expr int($factor*$inv2)]
  
  set lighter [format #%02x%02x%02x [expr {$bg0 + $add0}] \
      [expr {$bg1 + $add1}] \
      [expr {$bg2 + $add2}]]
  
  if {$lightness > 90} {
    # Use a darker color for the treeview and canvas
    set panel $shadow
    set thumb $bg
  } else {
    # Use the lighter color for the treeview and canvas, and
    # make the scroll thumb lighter
    set panel $light
    set thumb $light
  }
  lappend start_log "Computed background shades"
  lappend start_log "CoLoR_shadow: $shadow"
  lappend start_log "CoLoR_orig: $bg"
  #lappend start_log "CoLoR_light: $light"
  lappend start_log "CoLoR_lighter: $lighter"
  #lappend start_log "CoLoR_panel: $panel"
  #lappend start_log "CoLoR_thumb: $thumb"

  return [list $panel $thumb $lighter $light $shadow]
}

# If we get a font from gsettings, we have to arrange it in list fields
proc colors:sanitize_fontspec {font_in} {
  set font_inproc [string trim $font_in "'"]
  regsub -all {,} $font_inproc {} font_inproc
  set last [lindex $font_inproc end]
  set begin [lrange $font_inproc 0 end-1]
  #puts $begin
  #puts $last
  if {[string is integer -strict $last]} {
    set font_out "[list $begin] $last"
  } else {
    set font_out [list $font_inproc]
  }
  #puts $font_out
  return $font_out
}

# Take an rgb color and translate it to hex
proc colors:rgb2hex {rgb} {
  set lst [split $rgb {,}]
  set r_d [lindex $lst 0]
  set g_d [lindex $lst 1]
  set b_d [lindex $lst 2]
  set hex [format #%02x%02x%02x $r_d $g_d $b_d]
  return $hex
}
# Decide if a background needs white or black text for readablity

proc colors:contrast {hex} {
  set ret [catch {set rgb_bg [winfo rgb . $hex]} err]
  if {$ret} {
    gen_log:log E "$err"
    return ""
  }
  set bg0 [expr [lindex $rgb_bg 0] / 256 ]
  set bg1 [expr [lindex $rgb_bg 1] / 256 ]
  set bg2 [expr [lindex $rgb_bg 2] / 256 ]

  # Approximation of perceived lightness
  set lightness [expr ( ((2*$bg0) + $bg1 + (3*$bg2)) / 6 )]
  # Max lightness is 255.
  if {$lightness > 160} {
    set contrast #000000
  } else {
    set contrast #ffffff
  }
  #puts "$hex  $lightness"

  return $contrast
}

# Here's where we decide which decoration scheme to apply
proc colors:match_desktop {} {
  global env
  global cvscfg
  global colorglb
  global start_log
  global theme_system

  wm withdraw .
  
  # Create some widgets to see what the basic colors are
  label .testlbl -text "LABEL"
  set lblbg [lindex [.testlbl cget -background] 0]
  set lblfg [lindex [.testlbl cget -foreground] 0]
  destroy .testlbl
  
  text .testtxt
  set colorglb(textbg) [lindex [.testtxt configure -background] 4]
  set colorglb(textfg) [lindex [.testtxt configure -foreground] 4]
  destroy .testtxt
  
  # Hilight colors.  Get the colorful ones.
  entry .testent
  set colorglb(hlbg) [lindex [.testent configure -selectbackground] 4]
  set colorglb(hlfg) [lindex [.testent configure -selectforeground] 4]
  if {$colorglb(hlfg) eq {} } {
    # This happens on the Mac
    set colorglb(hlfg) [lindex [.testent configure -foreground] 4]
  }
  destroy .testent
  
  # Defaults
  set colorglb(guifont) TkDefaultFont
  set colorglb(lblfont) TkDefaultFont
  set colorglb(listboxfont) TkDefaultFont
  set colorglb(btnfont) TkDefaultFont
  set colorglb(menufont) TkMenuFont
  set colorglb(textfont) TkFixedFont
  
  set WSYS [tk windowingsystem]
  lappend start_log "Windowing system: $WSYS"
  set theme_system "unknown"
  
  if {$WSYS eq "x11"} {
    # If X11, see if we can sense our environment somehow
    if {$cvscfg(match_desktop)} {
      lappend start_log "Trying to find a destop theme"
      if {[info exists env(XDG_CURRENT_DESKTOP)]} {
        switch -glob -- $env(XDG_CURRENT_DESKTOP) {
          {*GNOME} -
          {*MATE} -
          {*XFCE} -
          {*COSMIC} -
          {*KDE} {
            if {[colors:get_gtk_theme]} { set theme_system "GTK" }
          }
          {CDE} {
            # CDE may or may not be running under XDG
            if {[colors:get_cde_params]} { set theme_system "CDE" }
            # Put the Help menu back on the right
            #tk::classic::restore menu
          }
          {*NsCDE} {
            # Like CDE. The palettes are in /usr/share/NsCDE/palettes
            # It's really FVWM. The current palette and colorsets are in FVWM_USERDIR,
            # usually ~/.NsCDE/Colorset.fvwmgen
            # also env(NSCDE_PALETTE)
            # Put the Help menu back on the right
            #tk::classic::restore menu
            if {[colors:get_cde_params]} { set theme_system "NsCDE" }
          }
          default {
            lappend start_log "I don't know how to theme XDG_CURRENT_DESKTOP=$env(XDG_CURRENT_DESKTOP)"
          }
        }
      }
      # It isn't an XDG_CURRENT_DESKTOP thing, but it could still be CDE
      if {$theme_system eq "unknown"} {
        if {[colors:get_cde_params]} {
          set theme_system "CDE"
          # Put the Help menu back on the right
          #tk::classic::restore menu
        } elseif {[colors:get_x11_resources]} {
          set theme_system "Xresources"
          lappend start_log "Using Xresources"
        }
      }
    # We aren't asked to match a theme, but we still respect Xdefaults
    } elseif {[colors:get_x11_resources]} {
      set theme_system "Xresources"
      lappend start_log "Using Xresources"
    }

    # OK it's really just X11
    if {$theme_system eq "unknown"} {
      set theme_system "tk_default"
      lappend start_log "Using tk's default GUI background"
      set bg  $lblbg
      set fg  $lblfg
      set hlbg "#4a6984" ;# skyblue2
      set hlfg "#ffffff"
      set textbg "#ffffff"
      set textfg "#000000"
      
      set colorglb(bg) $bg
      set colorglb(fg) $fg
      set colorglb(menubg) $bg
      set colorglb(menufg) $fg
      set colorglb(textbg) $textbg
      set colorglb(textfg) $textfg
      set colorglb(hlbg) $hlbg
      set colorglb(hlfg) $hlfg
      set colorglb(treefg) $fg
      set colorglb(canvfg) #000000

      # No theme system
      lassign [colors:shades $bg] panelbg thumb lighter light shadow
      set colorglb(canvbg) $panelbg
      set colorglb(treebg) $panelbg
      set colorglb(thumb) $thumb
      set colorglb(trough) $shadow
      set colorglb(lighter) $lighter
      set colorglb(light) $light
      set colorglb(shadow) $shadow
    }
  
    if {! [info exists colorglb(dialogfont)]} {
      set colorglb(dialogfont) TkHeadingFont
    }
    if {! [info exists colorglb(menufont)] } {
      set colorglb(menufont) TkMenuFont
    }
    if {! [info exists colorglb(lblfont)] } {
      set colorglb(lblfont) TkDefaultFont
    }
    if {! [info exists colorglb(btnfont)] } {
      set colorglb(btnfont) TkDefaultFont
    }
    if {! [info exists colorglb(listboxfont)] } {
      set colorglb(listboxfont) TkDefaultFont
    }
    if {! [info exists colorglb(textfont)] } {
      set colorglb(textfont) TkFixedFont
    }
    colors:add_options $theme_system
  } else {
    # We might be on MacOS (aqua) or Windows (win32)
    set bg $lblbg
    set fg $lblfg
    set colorglb(bg) $bg
    set colorglb(fg) $fg
    set colorglb(menubg) $bg
    set colorglb(menufg) $fg
    set colorglb(guifont) $colorglb(lblfont)
    set colorglb(dialogfont) TkHeadingFont
  
    # Non X11. MacOS or Windows
    lassign [colors:shades $bg] panelbg thumb lighter light shadow
    set colorglb(canvbg) $panelbg
    set colorglb(canvfg) $fg
    set colorglb(treebg) $panelbg
    set colorglb(treefg) $fg
    set colorglb(thumb) $thumb
    set colorglb(trough) $shadow
    set colorglb(lighter) $lighter
    set colorglb(light) $light
    set colorglb(shadow) $shadow
  }
  
  if {! [info exists colorglb(tooltipbg)]} {
    set colorglb(tooltipbg) #ffec8b ;# lightgoldenrod1
    set colorglb(tooltipfg) #000000
  }
  #lappend start_log "Scaling: [tk scaling]"
  lappend start_log "FoNt_textfont: $colorglb(textfont)"
  lappend start_log "FoNt_menufont: $colorglb(menufont)"
  lappend start_log "FoNt_btnfont: $colorglb(btnfont)"
  lappend start_log "FoNt_listboxfont: $colorglb(listboxfont)"
  lappend start_log "FoNt_guifont: $colorglb(guifont)"
  lappend start_log "FoNt_dialogfont: $colorglb(dialogfont)"
  lappend start_log "FoNt_tooltipfont: TkTooltipFont"
  
  lappend start_log "CoLoR_colorglb(bg): $colorglb(bg)"
  lappend start_log "CoLoR_colorglb(fg): $colorglb(fg)"
  foreach k [lsort [array names colorglb *??g]] {
    lappend start_log "CoLoR_colorglb($k): $colorglb($k)"
  }
  
  # Suppress tearoffs in menubars
  option add *tearOff 0
  
  # This makes tk_messageBox use our font.  The default tends to be terrible
  # no matter what platform
  catch {option add *Dialog.msg.font $colorglb(dialogfont) userDefault}
  catch {option add *Message.font $colorglb(dialogfont) userDefault}
  
  if {$WSYS eq "x11"} {
    ttk::style configure TScrollbar -background $colorglb(thumb) \
      -troughcolor $colorglb(trough) -arrowcolor $colorglb(fg)
    ttk::style map "TScrollbar" \
      -background [list disabled $colorglb(thumb) active $colorglb(lighter)]
  
    ttk::style configure TFrame -background $colorglb(bg) -foreground $colorglb(fg)
    ttk::style configure TLabel -background $colorglb(bg) -foreground $colorglb(fg) \
       -font $colorglb(guifont)
  
    # Caution when using ttk::button. It won't do at all on MacOS if you do
    # anything remotely fancy with buttons.
    ttk::style configure TButton -borderwidth 2 \
       -background $colorglb(bg) -foreground $colorglb(fg) \
       -activebackground $colorglb(shadow)
    ttk::style map "TButton" \
       -background [list disabled $colorglb(shadow) active $colorglb(shadow)]
  
    ttk::style configure TEntry -relief sunken -bd 2 \
       -fieldbackground $colorglb(textbg) -readonlybackground $colorglb(shadow) \
       -foreground $colorglb(textfg) -background $colorglb(textbg) \
       -font $colorglb(listboxfont)
    ttk::style map "TEntry" \
       -background [list readonly $colorglb(shadow) disabled $colorglb(shadow)]
  
    ttk::style configure TCheckbutton \
       -background $colorglb(bg) -foreground $colorglb(fg)
    ttk::style map "TCheckbutton" \
       -indicatorcolor [list selected $colorglb(hlbg)]
    # New style for things in the preferences dialog
    ttk::style configure Tabs.TCheckbutton \
      -background $colorglb(menubg) -foreground $colorglb(menufg)
    ttk::style configure Tabs.TRadiobutton \
      -background $colorglb(menubg) -foreground $colorglb(menufg)
    ttk::style configure Tabs.TLabel \
      -background $colorglb(menubg) -foreground $colorglb(menufg)
  
    ttk::style configure TRadiobutton \
       -background $colorglb(bg) -foreground $colorglb(fg)
    ttk::style map "TRadiobutton" \
       -indicatorcolor [list selected $colorglb(hlbg)]
  
    ttk::style configure TCombobox -fieldbackground $colorglb(textbg) \
      -arrowcolor $colorglb(fg) \
      -background $colorglb(bg) -foreground $colorglb(textfg) \
      -selectbackground $colorglb(hlbg) -selectforeground $colorglb(hlfg) \
      -font $colorglb(listboxfont)
    # font doesn't work tho ^
    ttk::style map "TCombobox" \
      -background [list active $colorglb(lighter)]
  
    # get some shades for the notebook
    lassign [colors:shades $colorglb(menubg)] panelbg thumb lighter light shadow
    ttk::style configure TNotebook \
      -background $panelbg -foreground $colorglb(menufg)
    ttk::style configure TNotebook.Tab \
      -background $colorglb(menubg) -foreground $colorglb(menufg)
    ttk::style map "TNotebook.Tab" \
      -background [list selected $light] \
      -foreground [list selected $colorglb(menufg)]
  
    ttk::style configure TSpinbox \
      -arrowcolor $colorglb(fg) -fieldbackground $colorglb(textbg) \
      -background $colorglb(menubg) -foreground $colorglb(textfg)
    ttk::style map "TSpinbox" \
      -background [list active $colorglb(lighter)]
  }
  
  # Style the treeview for all platforms, although some things won't
  # take on MacOS or Windows
  ttk::style configure Treeview \
    -background $colorglb(treebg) -foreground $colorglb(treefg) \
    -fieldbackground $colorglb(treebg) \
    -font $colorglb(listboxfont)
  ttk::style configure Treeview.Tree -selectbackground $colorglb(hlbg)
  ttk::style configure Treeview.Heading -font $colorglb(listboxfont) \
    -background $colorglb(bg) -foreground $colorglb(treefg)
  ttk::style configure Treeview.Heading -padding {4 0}
  ttk::style map "Treeview.Heading" \
    -background [list active $colorglb(light)]
  ttk::style configure Treeview.Cell -padding {2 0}
  ttk::style map "Treeview" \
    -background [list selected $colorglb(hlbg)] \
    -foreground [list selected $colorglb(hlfg)]
}
