Revision: 75518
          http://sourceforge.net/p/brlcad/code/75518
Author:   starseeker
Date:     2020-04-22 01:23:32 +0000 (Wed, 22 Apr 2020)
Log Message:
-----------
ditto fb Tcl interface

Modified Paths:
--------------
    brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt
    brlcad/branches/dm-fb-merge/src/libtclcad/CMakeLists.txt

Added Paths:
-----------
    brlcad/branches/dm-fb-merge/src/libtclcad/fb_obj.c

Removed Paths:
-------------
    brlcad/branches/dm-fb-merge/src/libdm/fb_obj.c

Modified: brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt        2020-04-22 
01:21:42 UTC (rev 75517)
+++ brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt        2020-04-22 
01:23:32 UTC (rev 75518)
@@ -69,7 +69,6 @@
   dm_util.c
   fb_generic.c
   fb_log.c
-  fb_obj.c
   fb_paged_io.c
   fb_rect.c
   fb_util.c

Deleted: brlcad/branches/dm-fb-merge/src/libdm/fb_obj.c
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/fb_obj.c      2020-04-22 01:21:42 UTC 
(rev 75517)
+++ brlcad/branches/dm-fb-merge/src/libdm/fb_obj.c      2020-04-22 01:23:32 UTC 
(rev 75518)
@@ -1,912 +0,0 @@
-/*                        F B _ O B J . C
- * BRL-CAD
- *
- * Copyright (c) 1997-2020 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @addtogroup libstruct fb */
-/** @{ */
-/** @file fb_obj.c
- *
- * A framebuffer object contains the attributes and
- * methods for controlling framebuffers.
- *
- */
-/** @} */
-
-#include "common.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include "tcl.h"
-#include "bu/cmd.h"
-#include "bu/color.h"
-#include "bu/getopt.h"
-#include "bu/malloc.h"
-#include "bu/str.h"
-#include "./include/private.h"
-#include "dm.h"
-
-/* defined in libfb/tcl.c */
-extern int fb_refresh(struct fb *ifp, int x, int y, int w, int h);
-
-
-#define FBO_CONSTRAIN(_v, _a, _b)              \
-    ((_v > _a) ? (_v < _b ? _v : _b) : _a)
-
-#define FB_OBJ_LIST_INIT_CAPACITY 8
-
-struct fb_obj {
-    struct bu_vls fbo_name;    /* framebuffer object name/cmd */
-    struct fbserv_obj fbo_fbs; /* fbserv object */
-    Tcl_Interp *fbo_interp;
-};
-
-static struct fb_obj fb_obj_list_init[FB_OBJ_LIST_INIT_CAPACITY];
-
-static struct fb_obj_list {
-    size_t capacity, size;
-    struct fb_obj *objs;
-} fb_objs;
-
-
-HIDDEN int
-fbo_coords_ok(struct fb *fbp, int x, int y)
-{
-    int width;
-    int height;
-    int errors;
-    width = fb_getwidth(fbp);
-    height = fb_getheight(fbp);
-
-    errors = 0;
-
-    if (x < 0) {
-       bu_log("fbo_coords_ok: Error!: X value < 0\n");
-       ++errors;
-    }
-
-    if (y < 0) {
-       bu_log("fbo_coords_ok: Error!: Y value < 0\n");
-       ++errors;
-    }
-
-    if (x > width - 1) {
-       bu_log("fbo_coords_ok: Error!: X value too large\n");
-       ++errors;
-    }
-
-    if (y > height - 1) {
-       bu_log("fbo_coords_ok: Error!: Y value too large\n");
-       ++errors;
-    }
-
-    if (errors) {
-       return 0;
-    } else {
-       return 1;
-    }
-}
-
-
-/*
- * Called when the object is destroyed.
- */
-HIDDEN void
-fbo_deleteProc(void *clientData)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-
-    /* close framebuffer */
-    fb_close(fbop->fbo_fbs.fbs_fbp);
-
-    bu_vls_free(&fbop->fbo_name);
-    memmove(fbop,
-           fbop + 1,
-           sizeof (struct fb_obj) * (fb_objs.objs + fb_objs.size - fbop));
-       fb_objs.size--;
-    bu_free((void *)fbop, "fbo_deleteProc: fbop");
-}
-
-
-/*
- * Close a framebuffer object.
- *
- * Usage:
- * procname close
- */
-HIDDEN int
-fbo_close_tcl(void *clientData, int argc, const char **UNUSED(argv))
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-
-    if (argc != 2) {
-       bu_log("ERROR: expecting two arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    /* Among other things, this will call dmo_deleteProc. */
-    Tcl_DeleteCommand(fbop->fbo_interp, bu_vls_addr(&fbop->fbo_name));
-
-    return BRLCAD_OK;
-}
-
-
-HIDDEN int
-fbo_tcllist2color(const char *str, unsigned char *pixel)
-{
-    int r, g, b;
-
-    if (sscanf(str, "%d %d %d", &r, &g, &b) != 3) {
-       bu_log("fb_clear: bad color spec - %s", str);
-       return BRLCAD_ERROR;
-    }
-
-    pixel[RED] = FBO_CONSTRAIN (r, 0, 255);
-    pixel[GRN] = FBO_CONSTRAIN (g, 0, 255);
-    pixel[BLU] = FBO_CONSTRAIN (b, 0, 255);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- * Clear the framebuffer with the specified color.
- * Otherwise, clear the framebuffer with black.
- *
- * Usage:
- * procname clear [rgb]
- */
-HIDDEN int
-fbo_clear_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int status;
-    RGBpixel pixel;
-    unsigned char *ms;
-
-
-    if (argc < 2 || 3 < argc) {
-       bu_log("ERROR: expecting only two or three arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (argc == 3) {
-       /*
-        * Decompose the color list into its constituents.
-        * For now must be in the form of rrr ggg bbb.
-        */
-       if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
-           bu_log("fb_cell: invalid color spec: %s.", argv[6]);
-           return BRLCAD_ERROR;
-       }
-
-       ms = pixel;
-    } else
-       ms = RGBPIXEL_NULL;
-
-    status = fb_clear(fbop->fbo_fbs.fbs_fbp, ms);
-
-    if (status < 0)
-       return BRLCAD_ERROR;
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname cursor mode x y
- */
-HIDDEN int
-fbo_cursor_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int mode;
-    int x, y;
-    int status;
-
-    if (argc != 5) {
-       bu_log("ERROR: expecting five arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[2], "%d", &mode) != 1) {
-       bu_log("fb_cursor: bad mode - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[3], "%d", &x) != 1) {
-       bu_log("fb_cursor: bad x value - %s", argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[4], "%d", &y) != 1) {
-       bu_log("fb_cursor: bad y value - %s", argv[4]);
-       return BRLCAD_ERROR;
-    }
-
-    status = fb_cursor(fbop->fbo_fbs.fbs_fbp, mode, x, y);
-    if (status == 0)
-       return BRLCAD_OK;
-
-    return BRLCAD_ERROR;
-}
-
-
-/*
- *
- * Usage:
- * procname getcursor
- */
-HIDDEN int
-fbo_getcursor_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int status;
-    int mode;
-    int x, y;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-
-    if (argc != 2
-       || !BU_STR_EQUIV(argv[1], "getcursor"))
-    {
-       bu_log("ERROR: unexpected argument(s)\n");
-       return BRLCAD_ERROR;
-    }
-
-    status = fb_getcursor(fbop->fbo_fbs.fbs_fbp, &mode, &x, &y);
-    if (status == 0) {
-       bu_vls_printf(&vls, "%d %d %d", mode, x, y);
-       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-       bu_vls_free(&vls);
-
-       return BRLCAD_OK;
-    }
-
-    return BRLCAD_ERROR;
-}
-
-
-/*
- * Refresh the entire framebuffer or that part specified by
- * a rectangle (i.e. x y width height)
- * Usage:
- * procname refresh [rect]
- */
-HIDDEN int
-fbo_refresh_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int x, y, w, h;                   /* rectangle to be refreshed */
-
-    if (argc < 2 || 3 < argc) {
-       bu_log("ERROR: expecting only two or three arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (argc == 2) {
-       /* refresh the whole display */
-       x = y = 0;
-       w = fbop->fbo_fbs.fbs_fbp->i->if_width;
-       h = fbop->fbo_fbs.fbs_fbp->i->if_height;
-    } else if (sscanf(argv[2], "%d %d %d %d", &x, &y, &w, &h) != 4) {
-       /* refresh rectangular area */
-       bu_log("fb_refresh: bad rectangle - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    return fb_refresh(fbop->fbo_fbs.fbs_fbp, x, y, w, h);
-}
-
-
-/*
- * Listen for framebuffer clients.
- *
- * Usage:
- * procname listen port
- *
- * Returns the port number actually used.
- *
- */
-HIDDEN int
-fbo_listen_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-
-    if (fbop->fbo_fbs.fbs_fbp == FB_NULL) {
-       bu_log("%s listen: framebuffer not open!\n", argv[0]);
-       return BRLCAD_ERROR;
-    }
-
-    if (argc != 2 && argc != 3) {
-       bu_log("ERROR: expecting only two or three arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (argc == 3) {
-       int port;
-
-       if (sscanf(argv[2], "%d", &port) != 1) {
-           bu_log("listen: bad value - %s\n", argv[2]);
-           return BRLCAD_ERROR;
-       }
-
-       if (port >= 0)
-           fbs_open(&fbop->fbo_fbs, port);
-       else {
-           fbs_close(&fbop->fbo_fbs);
-       }
-       bu_vls_printf(&vls, "%d", fbop->fbo_fbs.fbs_listener.fbsl_port);
-       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-       bu_vls_free(&vls);
-
-       return BRLCAD_OK;
-    }
-
-    /* return the port number */
-    /* argc == 2 */
-    bu_vls_printf(&vls, "%d", fbop->fbo_fbs.fbs_listener.fbsl_port);
-    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-    bu_vls_free(&vls);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- * Set/get the pixel value at position (x, y).
- *
- * Usage:
- * procname pixel x y [rgb]
- */
-HIDDEN int
-fbo_pixel_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-    int x, y;  /* pixel position */
-    RGBpixel pixel;
-
-    if (argc != 4 && argc != 5) {
-       bu_log("ERROR: expecting five arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    /* get pixel position */
-    if (sscanf(argv[2], "%d", &x) != 1) {
-       bu_log("fb_pixel: bad x value - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[3], "%d", &y) != 1) {
-       bu_log("fb_pixel: bad y value - %s", argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    /* check pixel position */
-    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, x, y)) {
-       bu_log("fb_pixel: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    /* get pixel value */
-    if (argc == 4) {
-       fb_rpixel(fbop->fbo_fbs.fbs_fbp, pixel);
-       bu_vls_printf(&vls, "%d %d %d", pixel[RED], pixel[GRN], pixel[BLU]);
-       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-       bu_vls_free(&vls);
-
-       return BRLCAD_OK;
-    }
-
-    /*
-     * Decompose the color list into its constituents.
-     * For now must be in the form of rrr ggg bbb.
-     */
-
-    /* set pixel value */
-    if (fbo_tcllist2color(argv[4], pixel) == BRLCAD_ERROR) {
-       bu_log("fb_pixel: invalid color spec - %s", argv[4]);
-       return BRLCAD_ERROR;
-    }
-
-    fb_write(fbop->fbo_fbs.fbs_fbp, x, y, pixel, 1);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname cell xmin ymin width height color
- */
-HIDDEN int
-fbo_cell_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int xmin, ymin;
-    long width;
-    long height;
-    size_t i;
-    RGBpixel pixel;
-    unsigned char *pp;
-
-
-    if (argc != 7) {
-       bu_log("ERROR: expecting seven arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[2], "%d", &xmin) != 1) {
-       bu_log("fb_cell: bad xmin value - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[3], "%d", &ymin) != 1) {
-       bu_log("fb_cell: bad ymin value - %s", argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    /* check coordinates */
-    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, xmin, ymin)) {
-       bu_log("fb_cell: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[4], "%ld", &width) != 1) {
-       bu_log("fb_cell: bad width - %s", argv[4]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[5], "%ld", &height) != 1) {
-       bu_log("fb_cell: bad height - %s", argv[5]);
-       return BRLCAD_ERROR;
-    }
-
-
-    /* check width and height */
-    if (width <=0  || height <=0) {
-       bu_log("fb_cell: width and height must be > 0");
-       return BRLCAD_ERROR;
-    }
-
-    /*
-     * Decompose the color list into its constituents.
-     * For now must be in the form of rrr ggg bbb.
-     */
-    if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
-       bu_log("fb_cell: invalid color spec: %s", argv[6]);
-       return BRLCAD_ERROR;
-    }
-
-    pp = (unsigned char *)bu_calloc(width*height, sizeof(RGBpixel), "allocate 
pixel array");
-    for (i = 0; i < width*height*sizeof(RGBpixel); i+=sizeof(RGBpixel)) {
-       pp[i] = pixel[0];
-       pp[i+1] = pixel[1];
-       pp[i+2] = pixel[2];
-    }
-    fb_writerect(fbop->fbo_fbs.fbs_fbp, xmin, ymin, width, height, pp);
-    bu_free((void *)pp, "free pixel array");
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname flush
- */
-HIDDEN int
-fbo_flush_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-
-    if (argc != 2
-       || !BU_STR_EQUIV(argv[1], "flush"))
-    {
-       bu_log("ERROR: expecting two arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    fb_flush(fbop->fbo_fbs.fbs_fbp);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname getheight
- */
-HIDDEN int
-fbo_getheight_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-
-    if (argc != 2
-       || !BU_STR_EQUIV(argv[1], "getheight"))
-    {
-       bu_log("ERROR: expecting two arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    bu_vls_printf(&vls, "%d", fb_getheight(fbop->fbo_fbs.fbs_fbp));
-    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-    bu_vls_free(&vls);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname getwidth
- */
-HIDDEN int
-fbo_getwidth_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-
-    if (argc != 2
-       || !BU_STR_EQUIV(argv[1], "getwidth"))
-    {
-       bu_log("ERROR: expecting two arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    bu_vls_printf(&vls, "%d", fb_getwidth(fbop->fbo_fbs.fbs_fbp));
-    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-    bu_vls_free(&vls);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname getsize
- */
-HIDDEN int
-fbo_getsize_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-
-    if (argc != 2
-       || !BU_STR_EQUIV(argv[1], "getsize"))
-    {
-       bu_log("ERROR: expecting two arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    bu_vls_printf(&vls, "%d %d",
-                 fb_getwidth(fbop->fbo_fbs.fbs_fbp),
-                 fb_getheight(fbop->fbo_fbs.fbs_fbp));
-    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
-    bu_vls_free(&vls);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- *
- * Usage:
- * procname cell xmin ymin width height color
- */
-HIDDEN int
-fbo_rect_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int xmin, ymin;
-    int xmax, ymax;
-    int width;
-    int height;
-    int i;
-    RGBpixel pixel;
-
-    if (argc != 7) {
-       bu_log("ERROR: expecting seven arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[2], "%d", &xmin) != 1) {
-       bu_log("fb_rect: bad xmin value - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[3], "%d", &ymin) != 1) {
-       bu_log("fb_rect: bad ymin value - %s", argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    /* check coordinates */
-    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, xmin, ymin)) {
-       bu_log("fb_rect: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[4], "%d", &width) != 1) {
-       bu_log("fb_rect: bad width - %s", argv[4]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[5], "%d", &height) != 1) {
-       bu_log("fb_rect: bad height - %s", argv[5]);
-       return BRLCAD_ERROR;
-    }
-
-
-    /* check width and height */
-    if (width <=0  || height <=0) {
-       bu_log("fb_rect: width and height must be > 0");
-       return BRLCAD_ERROR;
-    }
-
-    /*
-     * Decompose the color list into its constituents.
-     * For now must be in the form of rrr ggg bbb.
-     */
-    if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
-       bu_log("fb_rect: invalid color spec: %s", argv[6]);
-       return BRLCAD_ERROR;
-    }
-
-    xmax = xmin + width;
-    ymax = ymin + height;
-
-    /* draw horizontal lines */
-    for (i = xmin; i <= xmax; ++i) {
-       /* working on bottom line */
-       fb_write(fbop->fbo_fbs.fbs_fbp, i, ymin, pixel, 1);
-
-       /* working on top line */
-       fb_write(fbop->fbo_fbs.fbs_fbp, i, ymax, pixel, 1);
-    }
-
-    /* draw vertical lines */
-    for (i = ymin; i <= ymax; ++i) {
-       /* working on left line */
-       fb_write(fbop->fbo_fbs.fbs_fbp, xmin, i, pixel, 1);
-
-       /* working on right line */
-       fb_write(fbop->fbo_fbs.fbs_fbp, xmax, i, pixel, 1);
-    }
-
-    return BRLCAD_OK;
-}
-
-
-/*
- * Usage:
- * procname configure width height
- */
-HIDDEN int
-fbo_configure_tcl(void *clientData, int argc, const char **argv)
-{
-    struct fb_obj *fbop = (struct fb_obj *)clientData;
-    int width, height;
-
-    if (argc != 4) {
-       bu_log("ERROR: expecting four arguments\n");
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[2], "%d", &width) != 1) {
-       bu_log("fb_configure: bad width - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (sscanf(argv[3], "%d", &height) != 1) {
-       bu_log("fb_configure: bad height - %s", argv[3]);
-       return BRLCAD_ERROR;
-    }
-
-    /* configure the framebuffer window */
-    if (fbop->fbo_fbs.fbs_fbp != FB_NULL)
-       (void)fb_configure_window(fbop->fbo_fbs.fbs_fbp, width, height);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- * Generic interface for framebuffer object routines.
- * Usage:
- * procname cmd ?args?
- *
- * Returns: result of FB command.
- */
-HIDDEN int
-fbo_cmd(ClientData clientData, Tcl_Interp *UNUSED(interp), int argc, const 
char **argv)
-{
-    int ret;
-
-    static struct bu_cmdtab fbo_cmds[] = {
-       {"cell",        fbo_cell_tcl},
-       {"clear",       fbo_clear_tcl},
-       {"close",       fbo_close_tcl},
-       {"configure",   fbo_configure_tcl},
-       {"cursor",      fbo_cursor_tcl},
-       {"pixel",       fbo_pixel_tcl},
-       {"flush",       fbo_flush_tcl},
-       {"getcursor",   fbo_getcursor_tcl},
-       {"getheight",   fbo_getheight_tcl},
-       {"getsize",     fbo_getsize_tcl},
-       {"getwidth",    fbo_getwidth_tcl},
-       {"listen",      fbo_listen_tcl},
-       {"rect",        fbo_rect_tcl},
-       {"refresh",     fbo_refresh_tcl},
-       {(const char *)NULL, BU_CMD_NULL}
-    };
-
-    if (bu_cmd(fbo_cmds, argc, argv, 1, clientData, &ret) == BRLCAD_OK)
-       return ret;
-
-    bu_log("ERROR: '%s' command not found\n", argv[1]);
-    return BRLCAD_ERROR;
-}
-
-
-/*
- * Open/create a framebuffer object.
- *
- * Usage:
- * fb_open [name device [args]]
- */
-HIDDEN int
-fbo_open_tcl(void *UNUSED(clientData), Tcl_Interp *interp, int argc, const 
char **argv)
-{
-    struct fb_obj *fbop;
-    struct fb *ifp;
-    int width = 512;
-    int height = 512;
-    register int c;
-    struct bu_vls vls = BU_VLS_INIT_ZERO;
-    size_t i;
-
-    if (argc == 1) {
-       /* get list of framebuffer objects */
-       for (i = 0; i < fb_objs.size; i++) {
-           fbop = &fb_objs.objs[fb_objs.size];
-           Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), " ", (char 
*)NULL);
-       }
-
-       return BRLCAD_OK;
-    }
-
-    if (argc < 3) {
-       bu_vls_printf(&vls, "helplib fb_open");
-       Tcl_Eval(interp, bu_vls_addr(&vls));
-       bu_vls_free(&vls);
-       return BRLCAD_ERROR;
-    }
-
-    /* process args */
-    bu_optind = 3;
-    bu_opterr = 0;
-    while ((c = bu_getopt(argc, (char * const *)argv, "w:W:s:S:n:N:")) != -1) {
-       switch (c) {
-           case 'W':
-           case 'w':
-               width = atoi(bu_optarg);
-               break;
-           case 'N':
-           case 'n':
-               height = atoi(bu_optarg);
-               break;
-           case 'S':
-           case 's':
-               width = atoi(bu_optarg);
-               height = width;
-               break;
-           case '?':
-           default:
-               bu_log("fb_open: bad option - %s", bu_optarg);
-               return BRLCAD_ERROR;
-       }
-    }
-
-    if ((ifp = fb_open(argv[2], width, height)) == FB_NULL) {
-       bu_log("fb_open: bad device - %s", argv[2]);
-       return BRLCAD_ERROR;
-    }
-
-    if (fb_ioinit(ifp) != 0) {
-       bu_log("fb_open: fb_ioinit() failed.");
-       return BRLCAD_ERROR;
-    }
-
-    if (fb_objs.capacity == 0) {
-       fb_objs.capacity = FB_OBJ_LIST_INIT_CAPACITY;
-       fb_objs.objs = fb_obj_list_init;
-    } else if (fb_objs.size == fb_objs.capacity && fb_objs.capacity == 
FB_OBJ_LIST_INIT_CAPACITY) {
-       fb_objs.capacity *= 2;
-       fb_objs.objs = (struct fb_obj *)bu_malloc(
-               sizeof (struct fb_obj) * fb_objs.capacity,
-               "first resize of fb_obj list");
-    } else if (fb_objs.size == fb_objs.capacity) {
-       fb_objs.capacity *= 2;
-       fb_objs.objs = (struct fb_obj *)bu_realloc(
-               fb_objs.objs,
-               sizeof (struct fb_obj) * fb_objs.capacity,
-               "additional resize of fb_obj list");
-    }
-
-    /* append to list of fb_obj's */
-    fbop = &fb_objs.objs[fb_objs.size];
-    bu_vls_init(&fbop->fbo_name);
-    bu_vls_strcpy(&fbop->fbo_name, argv[1]);
-    fbop->fbo_fbs.fbs_fbp = ifp;
-    fbop->fbo_fbs.fbs_listener.fbsl_fbsp = &fbop->fbo_fbs;
-    fbop->fbo_fbs.fbs_listener.fbsl_fd = -1;
-    fbop->fbo_fbs.fbs_listener.fbsl_port = -1;
-    fbop->fbo_interp = interp;
-
-    fb_objs.size++;
-
-    (void)Tcl_CreateCommand(interp,
-                           bu_vls_addr(&fbop->fbo_name),
-                           (Tcl_CmdProc *)fbo_cmd,
-                           (ClientData)fbop,
-                           fbo_deleteProc);
-
-    /* Return new function name as result */
-    Tcl_ResetResult(interp);
-    Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), (char *)NULL);
-    return BRLCAD_OK;
-}
-
-
-int
-Fbo_Init(Tcl_Interp *interp)
-{
-    if (fb_objs.capacity == 0) {
-       fb_objs.capacity = FB_OBJ_LIST_INIT_CAPACITY;
-       fb_objs.objs = fb_obj_list_init;
-    }
-
-    (void)Tcl_CreateCommand(interp, "fb_open", (Tcl_CmdProc *)fbo_open_tcl,
-                           (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
-
-    return BRLCAD_OK;
-}
-
-
-/*
- * Local Variables:
- * mode: C
- * tab-width: 8
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */

Modified: brlcad/branches/dm-fb-merge/src/libtclcad/CMakeLists.txt
===================================================================
--- brlcad/branches/dm-fb-merge/src/libtclcad/CMakeLists.txt    2020-04-22 
01:21:42 UTC (rev 75517)
+++ brlcad/branches/dm-fb-merge/src/libtclcad/CMakeLists.txt    2020-04-22 
01:23:32 UTC (rev 75518)
@@ -33,6 +33,7 @@
   tkImgFmtPIX.c
   cmdhist_obj.c
   dm_obj.c
+  fb_obj.c
   dm_tcl.c
   )
 set_property(SOURCE tclcad_obj.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)

Copied: brlcad/branches/dm-fb-merge/src/libtclcad/fb_obj.c (from rev 75517, 
brlcad/branches/dm-fb-merge/src/libdm/fb_obj.c)
===================================================================
--- brlcad/branches/dm-fb-merge/src/libtclcad/fb_obj.c                          
(rev 0)
+++ brlcad/branches/dm-fb-merge/src/libtclcad/fb_obj.c  2020-04-22 01:23:32 UTC 
(rev 75518)
@@ -0,0 +1,912 @@
+/*                        F B _ O B J . C
+ * BRL-CAD
+ *
+ * Copyright (c) 1997-2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @addtogroup libstruct fb */
+/** @{ */
+/** @file fb_obj.c
+ *
+ * A framebuffer object contains the attributes and
+ * methods for controlling framebuffers.
+ *
+ */
+/** @} */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include "tcl.h"
+#include "bu/cmd.h"
+#include "bu/color.h"
+#include "bu/getopt.h"
+#include "bu/malloc.h"
+#include "bu/str.h"
+#include "../libdm/include/private.h"
+#include "dm.h"
+
+/* defined in libfb/tcl.c */
+extern int fb_refresh(struct fb *ifp, int x, int y, int w, int h);
+
+
+#define FBO_CONSTRAIN(_v, _a, _b)              \
+    ((_v > _a) ? (_v < _b ? _v : _b) : _a)
+
+#define FB_OBJ_LIST_INIT_CAPACITY 8
+
+struct fb_obj {
+    struct bu_vls fbo_name;    /* framebuffer object name/cmd */
+    struct fbserv_obj fbo_fbs; /* fbserv object */
+    Tcl_Interp *fbo_interp;
+};
+
+static struct fb_obj fb_obj_list_init[FB_OBJ_LIST_INIT_CAPACITY];
+
+static struct fb_obj_list {
+    size_t capacity, size;
+    struct fb_obj *objs;
+} fb_objs;
+
+
+HIDDEN int
+fbo_coords_ok(struct fb *fbp, int x, int y)
+{
+    int width;
+    int height;
+    int errors;
+    width = fb_getwidth(fbp);
+    height = fb_getheight(fbp);
+
+    errors = 0;
+
+    if (x < 0) {
+       bu_log("fbo_coords_ok: Error!: X value < 0\n");
+       ++errors;
+    }
+
+    if (y < 0) {
+       bu_log("fbo_coords_ok: Error!: Y value < 0\n");
+       ++errors;
+    }
+
+    if (x > width - 1) {
+       bu_log("fbo_coords_ok: Error!: X value too large\n");
+       ++errors;
+    }
+
+    if (y > height - 1) {
+       bu_log("fbo_coords_ok: Error!: Y value too large\n");
+       ++errors;
+    }
+
+    if (errors) {
+       return 0;
+    } else {
+       return 1;
+    }
+}
+
+
+/*
+ * Called when the object is destroyed.
+ */
+HIDDEN void
+fbo_deleteProc(void *clientData)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+
+    /* close framebuffer */
+    fb_close(fbop->fbo_fbs.fbs_fbp);
+
+    bu_vls_free(&fbop->fbo_name);
+    memmove(fbop,
+           fbop + 1,
+           sizeof (struct fb_obj) * (fb_objs.objs + fb_objs.size - fbop));
+       fb_objs.size--;
+    bu_free((void *)fbop, "fbo_deleteProc: fbop");
+}
+
+
+/*
+ * Close a framebuffer object.
+ *
+ * Usage:
+ * procname close
+ */
+HIDDEN int
+fbo_close_tcl(void *clientData, int argc, const char **UNUSED(argv))
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+
+    if (argc != 2) {
+       bu_log("ERROR: expecting two arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    /* Among other things, this will call dmo_deleteProc. */
+    Tcl_DeleteCommand(fbop->fbo_interp, bu_vls_addr(&fbop->fbo_name));
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+fbo_tcllist2color(const char *str, unsigned char *pixel)
+{
+    int r, g, b;
+
+    if (sscanf(str, "%d %d %d", &r, &g, &b) != 3) {
+       bu_log("fb_clear: bad color spec - %s", str);
+       return BRLCAD_ERROR;
+    }
+
+    pixel[RED] = FBO_CONSTRAIN (r, 0, 255);
+    pixel[GRN] = FBO_CONSTRAIN (g, 0, 255);
+    pixel[BLU] = FBO_CONSTRAIN (b, 0, 255);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Clear the framebuffer with the specified color.
+ * Otherwise, clear the framebuffer with black.
+ *
+ * Usage:
+ * procname clear [rgb]
+ */
+HIDDEN int
+fbo_clear_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int status;
+    RGBpixel pixel;
+    unsigned char *ms;
+
+
+    if (argc < 2 || 3 < argc) {
+       bu_log("ERROR: expecting only two or three arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (argc == 3) {
+       /*
+        * Decompose the color list into its constituents.
+        * For now must be in the form of rrr ggg bbb.
+        */
+       if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
+           bu_log("fb_cell: invalid color spec: %s.", argv[6]);
+           return BRLCAD_ERROR;
+       }
+
+       ms = pixel;
+    } else
+       ms = RGBPIXEL_NULL;
+
+    status = fb_clear(fbop->fbo_fbs.fbs_fbp, ms);
+
+    if (status < 0)
+       return BRLCAD_ERROR;
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname cursor mode x y
+ */
+HIDDEN int
+fbo_cursor_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int mode;
+    int x, y;
+    int status;
+
+    if (argc != 5) {
+       bu_log("ERROR: expecting five arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[2], "%d", &mode) != 1) {
+       bu_log("fb_cursor: bad mode - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[3], "%d", &x) != 1) {
+       bu_log("fb_cursor: bad x value - %s", argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[4], "%d", &y) != 1) {
+       bu_log("fb_cursor: bad y value - %s", argv[4]);
+       return BRLCAD_ERROR;
+    }
+
+    status = fb_cursor(fbop->fbo_fbs.fbs_fbp, mode, x, y);
+    if (status == 0)
+       return BRLCAD_OK;
+
+    return BRLCAD_ERROR;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname getcursor
+ */
+HIDDEN int
+fbo_getcursor_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int status;
+    int mode;
+    int x, y;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+    if (argc != 2
+       || !BU_STR_EQUIV(argv[1], "getcursor"))
+    {
+       bu_log("ERROR: unexpected argument(s)\n");
+       return BRLCAD_ERROR;
+    }
+
+    status = fb_getcursor(fbop->fbo_fbs.fbs_fbp, &mode, &x, &y);
+    if (status == 0) {
+       bu_vls_printf(&vls, "%d %d %d", mode, x, y);
+       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+       bu_vls_free(&vls);
+
+       return BRLCAD_OK;
+    }
+
+    return BRLCAD_ERROR;
+}
+
+
+/*
+ * Refresh the entire framebuffer or that part specified by
+ * a rectangle (i.e. x y width height)
+ * Usage:
+ * procname refresh [rect]
+ */
+HIDDEN int
+fbo_refresh_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int x, y, w, h;                   /* rectangle to be refreshed */
+
+    if (argc < 2 || 3 < argc) {
+       bu_log("ERROR: expecting only two or three arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (argc == 2) {
+       /* refresh the whole display */
+       x = y = 0;
+       w = fbop->fbo_fbs.fbs_fbp->i->if_width;
+       h = fbop->fbo_fbs.fbs_fbp->i->if_height;
+    } else if (sscanf(argv[2], "%d %d %d %d", &x, &y, &w, &h) != 4) {
+       /* refresh rectangular area */
+       bu_log("fb_refresh: bad rectangle - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    return fb_refresh(fbop->fbo_fbs.fbs_fbp, x, y, w, h);
+}
+
+
+/*
+ * Listen for framebuffer clients.
+ *
+ * Usage:
+ * procname listen port
+ *
+ * Returns the port number actually used.
+ *
+ */
+HIDDEN int
+fbo_listen_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+    if (fbop->fbo_fbs.fbs_fbp == FB_NULL) {
+       bu_log("%s listen: framebuffer not open!\n", argv[0]);
+       return BRLCAD_ERROR;
+    }
+
+    if (argc != 2 && argc != 3) {
+       bu_log("ERROR: expecting only two or three arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (argc == 3) {
+       int port;
+
+       if (sscanf(argv[2], "%d", &port) != 1) {
+           bu_log("listen: bad value - %s\n", argv[2]);
+           return BRLCAD_ERROR;
+       }
+
+       if (port >= 0)
+           fbs_open(&fbop->fbo_fbs, port);
+       else {
+           fbs_close(&fbop->fbo_fbs);
+       }
+       bu_vls_printf(&vls, "%d", fbop->fbo_fbs.fbs_listener.fbsl_port);
+       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+       bu_vls_free(&vls);
+
+       return BRLCAD_OK;
+    }
+
+    /* return the port number */
+    /* argc == 2 */
+    bu_vls_printf(&vls, "%d", fbop->fbo_fbs.fbs_listener.fbsl_port);
+    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+    bu_vls_free(&vls);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Set/get the pixel value at position (x, y).
+ *
+ * Usage:
+ * procname pixel x y [rgb]
+ */
+HIDDEN int
+fbo_pixel_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+    int x, y;  /* pixel position */
+    RGBpixel pixel;
+
+    if (argc != 4 && argc != 5) {
+       bu_log("ERROR: expecting five arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    /* get pixel position */
+    if (sscanf(argv[2], "%d", &x) != 1) {
+       bu_log("fb_pixel: bad x value - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[3], "%d", &y) != 1) {
+       bu_log("fb_pixel: bad y value - %s", argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    /* check pixel position */
+    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, x, y)) {
+       bu_log("fb_pixel: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    /* get pixel value */
+    if (argc == 4) {
+       fb_rpixel(fbop->fbo_fbs.fbs_fbp, pixel);
+       bu_vls_printf(&vls, "%d %d %d", pixel[RED], pixel[GRN], pixel[BLU]);
+       Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+       bu_vls_free(&vls);
+
+       return BRLCAD_OK;
+    }
+
+    /*
+     * Decompose the color list into its constituents.
+     * For now must be in the form of rrr ggg bbb.
+     */
+
+    /* set pixel value */
+    if (fbo_tcllist2color(argv[4], pixel) == BRLCAD_ERROR) {
+       bu_log("fb_pixel: invalid color spec - %s", argv[4]);
+       return BRLCAD_ERROR;
+    }
+
+    fb_write(fbop->fbo_fbs.fbs_fbp, x, y, pixel, 1);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname cell xmin ymin width height color
+ */
+HIDDEN int
+fbo_cell_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int xmin, ymin;
+    long width;
+    long height;
+    size_t i;
+    RGBpixel pixel;
+    unsigned char *pp;
+
+
+    if (argc != 7) {
+       bu_log("ERROR: expecting seven arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[2], "%d", &xmin) != 1) {
+       bu_log("fb_cell: bad xmin value - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[3], "%d", &ymin) != 1) {
+       bu_log("fb_cell: bad ymin value - %s", argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    /* check coordinates */
+    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, xmin, ymin)) {
+       bu_log("fb_cell: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[4], "%ld", &width) != 1) {
+       bu_log("fb_cell: bad width - %s", argv[4]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[5], "%ld", &height) != 1) {
+       bu_log("fb_cell: bad height - %s", argv[5]);
+       return BRLCAD_ERROR;
+    }
+
+
+    /* check width and height */
+    if (width <=0  || height <=0) {
+       bu_log("fb_cell: width and height must be > 0");
+       return BRLCAD_ERROR;
+    }
+
+    /*
+     * Decompose the color list into its constituents.
+     * For now must be in the form of rrr ggg bbb.
+     */
+    if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
+       bu_log("fb_cell: invalid color spec: %s", argv[6]);
+       return BRLCAD_ERROR;
+    }
+
+    pp = (unsigned char *)bu_calloc(width*height, sizeof(RGBpixel), "allocate 
pixel array");
+    for (i = 0; i < width*height*sizeof(RGBpixel); i+=sizeof(RGBpixel)) {
+       pp[i] = pixel[0];
+       pp[i+1] = pixel[1];
+       pp[i+2] = pixel[2];
+    }
+    fb_writerect(fbop->fbo_fbs.fbs_fbp, xmin, ymin, width, height, pp);
+    bu_free((void *)pp, "free pixel array");
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname flush
+ */
+HIDDEN int
+fbo_flush_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+
+    if (argc != 2
+       || !BU_STR_EQUIV(argv[1], "flush"))
+    {
+       bu_log("ERROR: expecting two arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    fb_flush(fbop->fbo_fbs.fbs_fbp);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname getheight
+ */
+HIDDEN int
+fbo_getheight_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+    if (argc != 2
+       || !BU_STR_EQUIV(argv[1], "getheight"))
+    {
+       bu_log("ERROR: expecting two arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    bu_vls_printf(&vls, "%d", fb_getheight(fbop->fbo_fbs.fbs_fbp));
+    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+    bu_vls_free(&vls);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname getwidth
+ */
+HIDDEN int
+fbo_getwidth_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+    if (argc != 2
+       || !BU_STR_EQUIV(argv[1], "getwidth"))
+    {
+       bu_log("ERROR: expecting two arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    bu_vls_printf(&vls, "%d", fb_getwidth(fbop->fbo_fbs.fbs_fbp));
+    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+    bu_vls_free(&vls);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname getsize
+ */
+HIDDEN int
+fbo_getsize_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+
+    if (argc != 2
+       || !BU_STR_EQUIV(argv[1], "getsize"))
+    {
+       bu_log("ERROR: expecting two arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    bu_vls_printf(&vls, "%d %d",
+                 fb_getwidth(fbop->fbo_fbs.fbs_fbp),
+                 fb_getheight(fbop->fbo_fbs.fbs_fbp));
+    Tcl_AppendResult(fbop->fbo_interp, bu_vls_addr(&vls), (char *)NULL);
+    bu_vls_free(&vls);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ *
+ * Usage:
+ * procname cell xmin ymin width height color
+ */
+HIDDEN int
+fbo_rect_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int xmin, ymin;
+    int xmax, ymax;
+    int width;
+    int height;
+    int i;
+    RGBpixel pixel;
+
+    if (argc != 7) {
+       bu_log("ERROR: expecting seven arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[2], "%d", &xmin) != 1) {
+       bu_log("fb_rect: bad xmin value - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[3], "%d", &ymin) != 1) {
+       bu_log("fb_rect: bad ymin value - %s", argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    /* check coordinates */
+    if (!fbo_coords_ok(fbop->fbo_fbs.fbs_fbp, xmin, ymin)) {
+       bu_log("fb_rect: coordinates (%s, %s) are invalid.", argv[2], argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[4], "%d", &width) != 1) {
+       bu_log("fb_rect: bad width - %s", argv[4]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[5], "%d", &height) != 1) {
+       bu_log("fb_rect: bad height - %s", argv[5]);
+       return BRLCAD_ERROR;
+    }
+
+
+    /* check width and height */
+    if (width <=0  || height <=0) {
+       bu_log("fb_rect: width and height must be > 0");
+       return BRLCAD_ERROR;
+    }
+
+    /*
+     * Decompose the color list into its constituents.
+     * For now must be in the form of rrr ggg bbb.
+     */
+    if (fbo_tcllist2color(argv[6], pixel) == BRLCAD_ERROR) {
+       bu_log("fb_rect: invalid color spec: %s", argv[6]);
+       return BRLCAD_ERROR;
+    }
+
+    xmax = xmin + width;
+    ymax = ymin + height;
+
+    /* draw horizontal lines */
+    for (i = xmin; i <= xmax; ++i) {
+       /* working on bottom line */
+       fb_write(fbop->fbo_fbs.fbs_fbp, i, ymin, pixel, 1);
+
+       /* working on top line */
+       fb_write(fbop->fbo_fbs.fbs_fbp, i, ymax, pixel, 1);
+    }
+
+    /* draw vertical lines */
+    for (i = ymin; i <= ymax; ++i) {
+       /* working on left line */
+       fb_write(fbop->fbo_fbs.fbs_fbp, xmin, i, pixel, 1);
+
+       /* working on right line */
+       fb_write(fbop->fbo_fbs.fbs_fbp, xmax, i, pixel, 1);
+    }
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Usage:
+ * procname configure width height
+ */
+HIDDEN int
+fbo_configure_tcl(void *clientData, int argc, const char **argv)
+{
+    struct fb_obj *fbop = (struct fb_obj *)clientData;
+    int width, height;
+
+    if (argc != 4) {
+       bu_log("ERROR: expecting four arguments\n");
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[2], "%d", &width) != 1) {
+       bu_log("fb_configure: bad width - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (sscanf(argv[3], "%d", &height) != 1) {
+       bu_log("fb_configure: bad height - %s", argv[3]);
+       return BRLCAD_ERROR;
+    }
+
+    /* configure the framebuffer window */
+    if (fbop->fbo_fbs.fbs_fbp != FB_NULL)
+       (void)fb_configure_window(fbop->fbo_fbs.fbs_fbp, width, height);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Generic interface for framebuffer object routines.
+ * Usage:
+ * procname cmd ?args?
+ *
+ * Returns: result of FB command.
+ */
+HIDDEN int
+fbo_cmd(ClientData clientData, Tcl_Interp *UNUSED(interp), int argc, const 
char **argv)
+{
+    int ret;
+
+    static struct bu_cmdtab fbo_cmds[] = {
+       {"cell",        fbo_cell_tcl},
+       {"clear",       fbo_clear_tcl},
+       {"close",       fbo_close_tcl},
+       {"configure",   fbo_configure_tcl},
+       {"cursor",      fbo_cursor_tcl},
+       {"pixel",       fbo_pixel_tcl},
+       {"flush",       fbo_flush_tcl},
+       {"getcursor",   fbo_getcursor_tcl},
+       {"getheight",   fbo_getheight_tcl},
+       {"getsize",     fbo_getsize_tcl},
+       {"getwidth",    fbo_getwidth_tcl},
+       {"listen",      fbo_listen_tcl},
+       {"rect",        fbo_rect_tcl},
+       {"refresh",     fbo_refresh_tcl},
+       {(const char *)NULL, BU_CMD_NULL}
+    };
+
+    if (bu_cmd(fbo_cmds, argc, argv, 1, clientData, &ret) == BRLCAD_OK)
+       return ret;
+
+    bu_log("ERROR: '%s' command not found\n", argv[1]);
+    return BRLCAD_ERROR;
+}
+
+
+/*
+ * Open/create a framebuffer object.
+ *
+ * Usage:
+ * fb_open [name device [args]]
+ */
+HIDDEN int
+fbo_open_tcl(void *UNUSED(clientData), Tcl_Interp *interp, int argc, const 
char **argv)
+{
+    struct fb_obj *fbop;
+    struct fb *ifp;
+    int width = 512;
+    int height = 512;
+    register int c;
+    struct bu_vls vls = BU_VLS_INIT_ZERO;
+    size_t i;
+
+    if (argc == 1) {
+       /* get list of framebuffer objects */
+       for (i = 0; i < fb_objs.size; i++) {
+           fbop = &fb_objs.objs[fb_objs.size];
+           Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), " ", (char 
*)NULL);
+       }
+
+       return BRLCAD_OK;
+    }
+
+    if (argc < 3) {
+       bu_vls_printf(&vls, "helplib fb_open");
+       Tcl_Eval(interp, bu_vls_addr(&vls));
+       bu_vls_free(&vls);
+       return BRLCAD_ERROR;
+    }
+
+    /* process args */
+    bu_optind = 3;
+    bu_opterr = 0;
+    while ((c = bu_getopt(argc, (char * const *)argv, "w:W:s:S:n:N:")) != -1) {
+       switch (c) {
+           case 'W':
+           case 'w':
+               width = atoi(bu_optarg);
+               break;
+           case 'N':
+           case 'n':
+               height = atoi(bu_optarg);
+               break;
+           case 'S':
+           case 's':
+               width = atoi(bu_optarg);
+               height = width;
+               break;
+           case '?':
+           default:
+               bu_log("fb_open: bad option - %s", bu_optarg);
+               return BRLCAD_ERROR;
+       }
+    }
+
+    if ((ifp = fb_open(argv[2], width, height)) == FB_NULL) {
+       bu_log("fb_open: bad device - %s", argv[2]);
+       return BRLCAD_ERROR;
+    }
+
+    if (fb_ioinit(ifp) != 0) {
+       bu_log("fb_open: fb_ioinit() failed.");
+       return BRLCAD_ERROR;
+    }
+
+    if (fb_objs.capacity == 0) {
+       fb_objs.capacity = FB_OBJ_LIST_INIT_CAPACITY;
+       fb_objs.objs = fb_obj_list_init;
+    } else if (fb_objs.size == fb_objs.capacity && fb_objs.capacity == 
FB_OBJ_LIST_INIT_CAPACITY) {
+       fb_objs.capacity *= 2;
+       fb_objs.objs = (struct fb_obj *)bu_malloc(
+               sizeof (struct fb_obj) * fb_objs.capacity,
+               "first resize of fb_obj list");
+    } else if (fb_objs.size == fb_objs.capacity) {
+       fb_objs.capacity *= 2;
+       fb_objs.objs = (struct fb_obj *)bu_realloc(
+               fb_objs.objs,
+               sizeof (struct fb_obj) * fb_objs.capacity,
+               "additional resize of fb_obj list");
+    }
+
+    /* append to list of fb_obj's */
+    fbop = &fb_objs.objs[fb_objs.size];
+    bu_vls_init(&fbop->fbo_name);
+    bu_vls_strcpy(&fbop->fbo_name, argv[1]);
+    fbop->fbo_fbs.fbs_fbp = ifp;
+    fbop->fbo_fbs.fbs_listener.fbsl_fbsp = &fbop->fbo_fbs;
+    fbop->fbo_fbs.fbs_listener.fbsl_fd = -1;
+    fbop->fbo_fbs.fbs_listener.fbsl_port = -1;
+    fbop->fbo_interp = interp;
+
+    fb_objs.size++;
+
+    (void)Tcl_CreateCommand(interp,
+                           bu_vls_addr(&fbop->fbo_name),
+                           (Tcl_CmdProc *)fbo_cmd,
+                           (ClientData)fbop,
+                           fbo_deleteProc);
+
+    /* Return new function name as result */
+    Tcl_ResetResult(interp);
+    Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), (char *)NULL);
+    return BRLCAD_OK;
+}
+
+
+int
+Fbo_Init(Tcl_Interp *interp)
+{
+    if (fb_objs.capacity == 0) {
+       fb_objs.capacity = FB_OBJ_LIST_INIT_CAPACITY;
+       fb_objs.objs = fb_obj_list_init;
+    }
+
+    (void)Tcl_CreateCommand(interp, "fb_open", (Tcl_CmdProc *)fbo_open_tcl,
+                           (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to