xgobi <- function(matrx,
                  collab     = dimnames(matrx)[[2]],
                  rowlab     = dimnames(matrx)[[1]],
                  colors     = NULL,
                  glyphs     = NULL,
                  erase      = NULL,
                  lines      = NULL,
                  linecolors = NULL,
                  resources  = NULL,
                  title      = NULL,
                  vgroups    = NULL,
                  std        = "mmx",
                  dev        = 2.0,
                  nlinkable  = NULL,
                  subset     = NULL,
                  display    = NULL)
{
    if (!missing(matrx))
    {
        ### data matrix ###
        x <- eval(matrx)
        if (sum(abs(x[!is.na(x)])) == Inf > 0)
        {
          cat("Sorry, xgobi can't handle Infs\n")
          return()
        }
        dfile <- tempfile("unix")
        ##KH cat(t(x), file = dfile, fill = 80)
        write.table(x, file = dfile, quote = FALSE,
                    row.names = FALSE, col.names = FALSE)

        ### Missing values, if present ###
        #if (sum(is.na(x)) > 0) {
        #  x.missing <- is.na(x)
        #  x.missing[x.missing == FALSE] <- 0
        #  x.missing[x.missing == TRUE] <- 1
        #  missingfile <- paste(dfile, ".missing", sep="")
        #  cat(t(x.missing), file = missingfile, fill = 80)
        #}
        ### Use the C code to do this ###

        ### Column labels ###
        if (missing(collab))
          collab <- dimnames(x)[[2]]
        else {
          # check data type
          if (!is.vector(collab) || !is.character(collab)) {
            cat("The 'collab' argument needs to be a character vector\n")
            return()
          }
        }
        if (length(collab) > 0)
        {
          colfile <- paste(dfile, ".col", sep="")
          cat(collab, file = colfile, sep="\n")
        }

        ### Row labels ###
        if (missing(rowlab))
          rowlab <- dimnames(x)[[1]]
        else {
          # check data type
          if (!is.vector(rowlab) || !is.character(rowlab)) {
            cat("The 'rowlab' argument needs to be a character vector\n")
            return()
          }
        }
        if (length(rowlab) > 0) {
            rowfile <- paste(dfile, ".row", sep="")
            cat(rowlab, file = rowfile, sep="\n")
        }

        ### Variable groups ###
        if (!missing(vgroups)) {
            # check data type
            if (!is.vector(vgroups) || !is.numeric(vgroups)) {
              cat("The 'vgroups' argument needs to be a numeric vector\n")
              return()
            }

            vgroupfile <- paste(dfile, ".vgroups", sep="")
            cat(vgroups, file = vgroupfile, sep="\n")
        }

        ### Colors ###
        if (!missing(colors)) {
            # check data type
            if (!is.vector(colors) || !is.character(colors)) {
              cat("The 'colors' argument needs to be a character vector\n")
              return()
            }
            colorfile <- paste(dfile, ".colors", sep="")
            cat(colors, file = colorfile, sep="\n")
        }
        ### Glyphs ###
        if (!missing(glyphs))
        {
            # check data type
            if (!is.vector(glyphs) || !is.numeric(glyphs)) {
              cat("The 'glyphs' argument needs to be a numeric vector\n")
              return()
            }
            glyphfile <- paste(dfile, ".glyphs", sep="")
            cat(glyphs, file = glyphfile, sep="\n")
        }
        ### Erase ###
        if (!missing(erase))
        {
            # check data type
            if (!is.vector(erase) || !is.numeric(erase)) {
              cat("The 'erase' argument needs to be a numeric vector\n")
              return()
            }
            erasefile <- paste(dfile, ".erase", sep="")
            cat(erase, file = erasefile, sep="\n")
        }

        ### Connected lines ###
        if (!missing(lines))
        {
            # check data type
            if (!is.matrix(lines) || !is.numeric(lines) || dim(lines)[2] != 2) {
                cat("The 'lines' argument must be a numeric 2-column matrix\n")
                return()
            }

            linesfile <- paste(dfile, ".lines", sep="")
            unix(paste("rm -f", linesfile), output=F)
            if (nrow(lines) > 0) {
                for (i in 1:nrow(lines))
                    cat(lines[i,], "\n", file = linesfile, append=T)
            }
            ### Line colors ###
            if (!missing(linecolors)) {
                # check data type
                if (!is.vector(linecolors) || !is.character(linecolors)) {
                   cat("The 'linecolors' argument must be a character vector\n")
                   return()
                }
                linecolorfile <- paste(dfile, ".linecolors", sep="")
                cat(linecolors, file = linecolorfile, sep="\n")
            }
        }
        ### Resources ###
        if (!missing(resources))
        {
            # check data type
            if (!is.vector(resources) || !is.character(resources)) {
                cat("The 'resources' argument must be a character vector\n")
                return()
            }
            resourcefile <- paste(dfile, ".resources", sep="")
            cat(resources, file = resourcefile, sep	="\n")
        }
        ### nlinkable ###
        if (!missing(nlinkable)) {
            # check data type
            nlinkable <- as.integer(nlinkable)
            if (length(nlinkable) > 1) {
                cat("The 'nlinkable' argument must be a scalar integer\n")
                return()
            }
            linkablefile <- paste(dfile, ".nlinkable", sep="")
            cat(nlinkable, "\n", file = linkablefile)
        }
        ### subset ###
        subsetarg <- ""
        if (!missing(subset)) {
            # check data type
            subset <- as.integer(subset)
            if (length(subset) > 1) {
                cat("The 'subset' argument must be a scalar integer\n")
                return()
            }
            else if (subset == 0 || subset > nrow(x)) {
                cat("The 'subset' argument must be >0 and <= nrows\n")
                return()
            }
            subsetarg <- paste(" -subset ", subset, sep="")
        }

        ##KH args <- paste("-s -std", std, "-dev", dev)
        args <- paste("-std", std, "-dev", dev)
        if (subsetarg != "")
            args <- paste(args, subsetarg, sep=" ")

        if (!missing(display)) {
            if (!is.character(display))
                warning("display must be a character string")
            else
                args <- paste("-display", display, args)
        }

        if (!missing(title)) {
            if (!is.character(title)) {
                warning("title must be a character string")
                title <- deparse(substitute(matrx))
            }
        }
        else
            title <- deparse(substitute(matrx))
        args <- paste("-title", paste("'", title, "'", sep=""), args)

#
# Note to installer:
# Here you will need to specify the path to the xgobi executable
# on your system.
        ##KH path <- paste("/usr/dfs/xgobi/src/")
#
        ##KH command <- paste(path, "xgobi", sep="")
        ##KH command <- paste(command, args)
        ##KH command <- paste(command, nrow(x), ncol(x),
        ##KH     search()[1], dfile, "&")
        command <- paste("xgobi", args, dfile, "&")
        cat(command, "\n")

        ##KH invisible(unix(command,output.to.S=F))
        invisible(system(command, FALSE))
    }
    else
      cat("Matrix argument required\n")
}
xgvis <-
  function(dmat       = NULL,
           edges      = NULL,
           pos        = NULL,
           rowlab     = NULL,
           colors     = NULL,
           glyphs     = NULL,
           erase      = NULL,
           lines      = NULL,
           linecolors = NULL,
           resources  = NULL,
           display    = NULL)
{
  ##KH
  FILES <- NULL
    
  if (missing(edges) && missing(pos) && missing(dmat)) {
    cat("One of dmat, edges, or pos must be present\n")
    return()
  }

  ##KH tpath <- getenv("S_TMP")
  ##KH if(nchar(tpath) == 0) tpath <- getenv("TEMP")
  ##KH basefile <- paste(tpath, tempfile("xgvis"), sep = "/")
  basefile <- tempfile("xgvis")

  ### distance matrix ###
  if (!missing(dmat)) {
    dmat <- eval(dmat)
    if (sum(abs(dmat[!is.na(dmat)])) == Inf > 0) {
      cat("xgvis can't handle Infs in dmat, replaced with NA\n")
      dmat[dmat==Inf] <- NA
    }
    dfile <- paste(basefile, ".dist", sep="")
    write(t(dmat), file = dfile, ncolumns = ncol(dmat))
    ##KH on.exit(unlink(dfile), add=T)
    FILES <- c(FILES, dfile)
    on.exit(unlink(FILES))
  }

  ### Edges ###
  if (!missing(edges))
    {
      # check data type
      if (!is.matrix(edges) || !is.numeric(edges) || dim(edges)[2] != 2) {
        cat("The `edges' argument must be a numeric 2-column matrix\n")
        return()
      }

      edgesfile <- paste(basefile, ".edges", sep="")
      if (nrow(edges) > 0) {
	write(t(edges), file = edgesfile, ncol=2)
      }
      ##KH on.exit(unlink(edgesfile), add=T)
      FILES <- c(FILES, edgesfile)
      on.exit(unlink(FILES))      
    }

  ### position matrix ###
  if (!missing(pos)) {
    pos <- eval(pos)
    if (sum(abs(pos[!is.na(pos)])) == Inf > 0)
      {
        cat("xgvis can't handle Inf in pos; replaced with NA\n")
        pos[pos==Inf] <- NA
      }
    pfile <- paste(basefile, ".pos", sep="")
    write(t(pos), file = pfile, ncolumns = ncol(pos))
    ##KH on.exit(unlink(pfile), add = T)
    FILES <- c(FILES, pfile)
    on.exit(unlink(FILES))
  }

  ### Row labels ###
  if (!missing(rowlab))
    # check data type
    if (!is.vector(rowlab) || !is.character(rowlab)) {
      cat("The `rowlab' argument needs to be a character vector\n")
      return()
    }
  if (length(rowlab) > 0) {
    rowfile <- paste(basefile, ".row", sep="")
    write(rowlab, file = rowfile, ncol=1)
    ##KH on.exit(unlink(rowfile), add = T)
    FILES <- c(FILES, rowfile)
    on.exit(unlink(FILES))
  }

  ### Colors ###
  if (!missing(colors)) {
    # check data type
    if (!is.vector(colors) || !is.character(colors)) {
      cat("The `colors' argument needs to be a character vector\n")
      return()
    }
    colorfile <- paste(basefile, ".colors", sep="")
    write(colors, file = colorfile, ncol=1)
    ##KH on.exit(unlink(colorfile), add = T)
    FILES <- c(FILES, colorfile)
    on.exit(unlink(FILES))
  }
  
  ### Glyphs ###
  if (!missing(glyphs)) {
    # check data type
    if (!is.vector(glyphs) || !is.numeric(glyphs)) {
      cat("The `glyphs' argument needs to be a numeric vector\n")
      return()
    }
    glyphfile <- paste(basefile, ".glyphs", sep="")
    write(glyphs, file = glyphfile, ncol=1)
    ##KH on.exit(unlink(glyphfile), add = T)
    FILES <- c(FILES, glyphfile)
    on.exit(unlink(FILES))
  }
  
  ### Erase ###
  if (!missing(erase)) {
    # check data type
    if (!is.vector(erase) || !is.numeric(erase)) {
      cat("The `erase' argument needs to be a numeric vector\n")
      return()
    }
    erasefile <- paste(basefile, ".erase", sep="")
    write(erase, file = erasefile, ncol=1)
    ##KH on.exit(unlink(erasefile), add = T)
    FILES <- c(FILES, erasefile)
    on.exit(unlink(FILES))
  }

  ### Connected lines ###
  if (!missing(lines)) {
    # check data type
    if (!is.matrix(lines) || !is.numeric(lines) || dim(lines)[2] != 2) {
      cat("The `lines' argument must be a numeric 2-column matrix\n")
      return()
    }

    linesfile <- paste(basefile, ".lines", sep="")
    if (nrow(lines) > 0) {
      write(t(lines), file = linesfile, ncol=2)
      ##KH on.exit(unlink(linesfile), add = T)
      FILES <- c(FILES, linesfile)
      on.exit(unlink(FILES))
    }
  }

  ### Line colors ###
  if ((!missing(lines) || !missing(edges)) && !missing(linecolors)) {
    # check data type
    if (!is.vector(linecolors) || !is.character(linecolors)) {
      cat("The `linecolors' argument must be a character vector\n")
      return()
    }
    linecolorfile <- paste(basefile, ".linecolors", sep="")
    write(linecolors, file = linecolorfile, ncol=1)
    ##KH on.exit(unlink(linecolorfile), add = T)
    FILES <- c(FILES, linecolorfile)
    on.exit(unlink(FILES))
  }

  ### Resources ###
  if (!missing(resources)) {
    # check data type
    if (!is.vector(resources) || !is.character(resources)) {
      cat("The `resources' argument must be a character vector\n")
      return()
    }
    resourcefile <- paste(basefile, ".resources", sep="")
    write(resources, file = resourcefile, ncol=1)
    ##KH on.exit(unlink(resourcefile), add = T)
    FILES <- c(FILES, resourcefile)
    on.exit(unlink(FILES))
  }


  # Note to installer:
  # Here you need to specify the path to the xgvis batch file/ executable
  # on your system.
  #
  # dos example:
  #  xgpath <- "c:/packages/xgobi/xgvis.bat"
  # unix example:
  ##KH xgpath <- "/usr/dfs/xgobi/joint/src/xgvis"
  ##KH command <- paste(xgpath, basefile)
  command <- paste("xgvis", basefile)
  cat(command, "\n")
  # dos:
  #  invisible(dos(command, multi = F, minimized = T,
  #     output.to.S = F, translate = T))
  # unix:
  ##KH invisible(unix(command))
  invisible(system(command))
}
