Subversion Repositories DIN Is Noise

Rev

Rev 2097 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* bit_display.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/


#include "bit_display.h"
#include "dingl.h"

bit_display::bit_display (int w, int h) {
  num_bits = 0;
  lsnr = 0;
  prev_id = -1;
  set_size (w, h);
}

void bit_display::set_size (int w, int h) {
  set_extents (extents.left, extents.bottom, extents.left + w, extents.bottom + h);
  set_pos (posx, posy);
}

void bit_display::set_pos (int x, int y) {
  widget::set_pos (x, y);
  calc_visual_params ();
}

void bit_display::set (void* bytes, int num_bytes) { // show bits of the given bytes
  num_bits = 8 * num_bytes;
  last_bit = num_bits - 1;
  bits.resize (num_bits); // init bit array
  unsigned char* pchar = (unsigned char *) bytes; // treat as character array
  for (int i = 0, k = 0; i < num_bytes; ++i) { // number of bytes = number of characters now
    unsigned char ci = pchar[i]; // ith character
    for (int j = 0; j < 8; ++j) { // extract bits of this character and store in bit array
      unsigned char tb = (ci & 0x80) >> 7; // extract left most bit
      bits[k++] = tb;
      ci = ci << 1; // left shift character by 1 bit
    }
  }
  calc_visual_params ();
}

void bit_display::calc_visual_params () {
  if (num_bits) {
    d_width = int (extents.width / num_bits); // display width for each bit
    int width = d_width * num_bits; // total width occupied by displayed bits
    xstart = extents.left;
    xend = xstart + width;
  }
}

extern int mousex, mouseyy;

int bit_display::find_bit_id () {
  if (mousex < xstart) return 0;
  else if (mousex > xend) return last_bit;
  return (mousex - xstart) / d_width;;
}

int bit_display::handle_input () {
  int ret = widget::handle_input ();
  if (hover) {
    if (lmb) {
      cur_id = find_bit_id ();
      if (cur_id != prev_id) {
        prev_id = cur_id;
        bits[cur_id] = !bits[cur_id];
        if (lsnr) lsnr->changed (*this);
      }
    } else prev_id = -1;
  }
  return ret;
}

void bit_display::draw () {
  glColor3f (clr.r, clr.g, clr.b);
  glPolygonMode (GL_FRONT, GL_LINE);
  glRecti (xstart, extents.bottom, xend, extents.top);
  int xl = xstart, xr = xl;
  for (int i = 0; i < num_bits; ++i) {
    unsigned char bi = bits[i];
    if (bi) glPolygonMode (GL_FRONT, GL_FILL); else glPolygonMode (GL_FRONT, GL_LINE);
    xr = xl + d_width;
    glRecti (xl, extents.bottom, xr, extents.top);
    xl = xr;
  }
  glPolygonMode (GL_FRONT, GL_FILL);
}

void bit_display::get_color (ucolor_t* uc) {
  unsigned char* pchar = (unsigned char*) uc;
  for (int i = 0, j = 0; i < 3; ++i) {
    unsigned char uci = 0;
    for (int k = 7; k > -1; --k) {
      unsigned char bj = bits[j++];
      uci = uci | (bj << k);
    }
    pchar[i] = uci;
  }
}