/*	The Transactor Structure Browser (SB) V1.0
 *	From Transactor Magazine, Volume 7, Issue 6
 *
 *	By Nick Sullivan and Chris Zamara (AHA!) (c) 1986
 *
 *	SB displays system structures via pointers found
 *	in other structures. You start from IntuitionBase.
 *
 *	Structures implemented in V1.0:
 *	IntuitionBase, Window, Screen, RastPort, BitMap, Gadget
 *
 *	Usage is through Intuition, clicking on a structure member
 *	names to display info or a new structure.
 *
 *	*****  THIS PROGRAM MAY BE FREELY DISTRIBUTED  *****
 */

/* include not needed for Aztec C using provided makefile */

/* I keep all the files in directory sb on df1:
 * To keep the system happy, I 'ASSIGN SB: DF1:SB' then 'CD SB:'. GG.
 */ 


#include "sb:sb.h"
#define MIN(x,y) ((x)<(y)?(x):(y))
#define FLAGFIELDS 4
extern struct IntuitionBase *IntuitionBase;
extern struct IntuiText ChoiceText[], BackIText;
APTR OpenLibrary ();
int level = 0; /* current level of nesting */
static char textlines[MAXGADG + 1][80];
extern void PrIntuiBase(), HexLine();

void main()
{
int choice = -1;
  SetupGadg();
  OpenStuff(); /* open intuition library & window */
  while (choice) {
    putHeader("Choose a library structure", NULL);
    ChoiceText[0].IText = (UBYTE *)" Intuition       struct Library";
    BackIText.IText = (UBYTE *)"  Quit  Program";
    switch (choice = GetChoice(1)) {
      case 1:
        PrIntuiBase ("The IntuitionBase structure", IntuitionBase);
        break;
    }
  }
  CloseOut();
}


void PrIntuiBase (string, IBase) char *string; struct IntuitionBase *IBase;
{
static struct StructData structdata[] = {
     { "(LibMode",           "struct Library)", 0, SZ(Library) },
     { "(ViewLord",          "struct View)",    0, SZ(View)    },
     { " ActiveWindow",      "struct Window *", 5, PTRSIZE     },
     { " ActiveScreen",      "struct Screen *", 5, PTRSIZE     },
     { " FirstScreen",       "struct Screen *", 5, PTRSIZE     }
  };
int sum, choice = -1;
  level++;
  while (choice) {
    sum = SetOptionText(string, structdata, (APTR)IBase, DATASIZE, 0);
    switch (choice = GetChoice(DATASIZE)) {
      case 3:
        if (IBase->ActiveWindow)
          PrWindow("The currently active window", IBase->ActiveWindow);
        break;
      case 4:
        PrScreen("The currently active screen", IBase->ActiveScreen);
        break;
      case 5:
        PrScreen("The first screen on Intuition's list", IBase->FirstScreen);
        break;
    }
  }
  level--;
}


void put (option, stuff, base, offset)
int option; struct StructData *stuff; char *base; int offset;
{
register long lnum;
register int  inum;
char buf[40];
int i;
  sprintf(textlines[option], "%-16s%-24s", stuff->membername, stuff->membertype);
  switch (stuff->printtype) {
    case 0:			/* don't print anything */
      buf[0] = '\0';
      break;
    case 1:			/* print a long */
      lnum = *(long *)(base + offset);
      sprintf(buf, "$%8lx  %0ld", lnum, lnum);
      break;
    case 2:			/* print an int */
      inum = *(short *)(base + offset);
      sprintf(buf, "$%8x  %10d", inum, inum);
      break;
    case 3:			/* print a byte */
      inum = *(base + offset);
      sprintf(buf, "$%8x  %10d", inum, inum);
      break;
    case 4:			/* print a string */
      if (!(lnum = *(long *)(base + offset) ))
        sprintf(buf, "NULL");
      else {
        for (i = 0; i < 30 && *((char *)lnum + i); i++)
          buf[i + 1] = *((char *)lnum + i);
        buf[0] = buf[i + 1] = '\"';
        buf[i + 2] = '\0';
        if (*((char *)lnum + i))
          strcat(buf, "...");
      }
      break;
    case 5:			/* print a pointer */
      if (!(lnum = *(long *)(base + offset) ))
        sprintf(buf, "NULL");
      else
        sprintf(buf, "$%8lx  %10ld", lnum, lnum);
      break;
    case 11:			/* print a long */
      lnum = *(long *)(base + offset);
      sprintf(buf, "$%8lx  %10lu", lnum, lnum);
      break;
    case 12:			/* print an int */
      inum = *(short *)(base + offset);
      sprintf(buf, "$%8x  %10u", inum, inum);
      break;
    case 13:			/* print a byte */
      inum = *(base + offset);
      sprintf(buf, "$%8x  %10u", inum, inum);
      break;
  }
  strcat(textlines[option], buf);
  ChoiceText[option].IText = (UBYTE *)textlines[option];
}


void FlagPrint(string, names, flags)
char *string, **names; ULONG flags;
{
int i, line, fields = FLAGFIELDS;
char buf[32];
  SetBackText(1); /* 'prev level' */
  for (i = 0; i < 8; i++) {
    strcpy(textlines[i], "-");
    ChoiceText[i].IText = (UBYTE *)textlines[i];
  }
  putHeader(string, NULL);
  for (i = line = 0; i < 32; i++) {
    if ((flags & (1L << i)) && names[i]) {
      sprintf(buf, "%-19s", names[i]);
      strcat(textlines[line], buf);
      if (!--fields) {
        ChoiceText[line].IText = (UBYTE *)textlines[line];
        line++;
        fields = FLAGFIELDS;
      }
    }
  }
  if (fields < FLAGFIELDS)
    ChoiceText[line].IText = (UBYTE *)textlines[line];
  while (GetChoice(line + 1))
    ;
}


void HexDump(string, address, unit, size)
char *address, *string; int unit; long size;
{
int line = 0, c;
char *buf[80];
  BackIText.IText = (UBYTE *)" Exit Hex Dump  ";
  if (size == -1)
    size = 0x7ffff;
  do {
    sprintf(buf, "%s from %lx (%ld)", string, address, address);
    putHeader(buf, NULL);
    if (line == MAXGADG)
      line = 0;
    while (line < MAXGADG && size > 0) {
      HexLine(address, unit, line++, size);
      size -= 16;
      address += 16;
    }
    c = GetChoice(size > 0 ? MAXGADG + 1 : line);
  } while (size > 0 && c == MOREGADG);
}


void HexLine (address, unit, line, size)
UBYTE *address; int unit, line; long size;
{
USHORT i, j;
char buf[80];
static char hexdigit[] = "0123456789ABCDEF";
  sprintf(textlines[line], "-%6lx: ", address);
  for (i = 0; i < MIN(size, 16); i += unit) {
    switch (unit) {
      case BYTESIZE:
        j = *(address + i);
        sprintf(buf, "%c%c ", hexdigit[j / 16], hexdigit[j % 16]);
        break;
      case INTSIZE:
        sprintf(buf, "%04x ", *(short *)(address + i));
        break;
      case PTRSIZE:
        sprintf(buf, "%08lx ", *(long *)(address + i));
        break;
    }
    strcat(textlines[line], buf);
  }
  ChoiceText[line].IText = (UBYTE *)textlines[line];
}


int SetOptionText (hdrtext, data, object, size, offset)
char *hdrtext;
struct StructData *data;
APTR object;
int size, offset;
{
int i, sum;
  SetBackText( offset ? 1 : 0);
  putHeader(hdrtext, object);
  for (i = sum = 0; i < size; i++) {
    put(i, &data[i], object, sum + offset);
    sum += data[i].datasize;
  }
  return (sum + offset);
}
    

void PrString(heading, string) char *heading, *string;
{
char *newstring, *malloc();
  putHeader(heading, NULL);
  newstring = malloc(strlen(string) + 1);
  *newstring = '-';
  strcpy(newstring + 1, string);
  ChoiceText[0].IText = (UBYTE *)newstring;
  GetChoice(1);
  free(newstring);
}
