macro_file bugrep;

/* Below are are some constants used to simplify the building of the
   user information dialog */
#define dbfilename 'bugrep'
#define dbpagename 'userinfo.cfg'
#define column1 1
#define column2 20
#define column3 60
#define column4 80
#define length1 38
#define length2 23

/* Include header files for external functions we want to use */
#include metools.sh
#include windows.sh
#include dialog.sh
#include commdlg.sh
#include print.sh

global
{
  str name '!bugrepname';
  str email '!bugrepemail';
  str mfr '!bugrepmfr';
  str cpu '!bugrepcpu';
  str vcard '!bugrepvcard';
  str mavail '!bugrepmavail';
  str nettype '!bugrepnettype';
  str netver '!bugrepnetver';
  str os '!bugrepos';
  int mewnet '!bugrepmewnet';
  str desc '!bugrepdesc';
  str number '!bugrepnumber';
  int builtonce '!bugrepbuiltonce';
  int repwin '!bugrepwindow';
  int outwin '!bugrepoutputwin';
}


int getuserinfo()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: getuserinfo

Description:  Builds a dialog box and gets user information to build a bug report

Returns: 1 if user pressed OK and information was saved to the globals.
         0 if user pressed Cancel

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  int ddlg;
  /* Create the dialog box and set up the dialog controls */
  DlgCreate(ddlg);
  DlgAddCtrl(ddlg, Dlg_Static, 'Name:', column1, 1, 0, 0, 1000, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, Name, column2, Dlg_PosOffset, length1, 1, 1005, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Email:', column3, Dlg_PosOffset, 0, 0, 1010, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, Email, column3 + 8, Dlg_PosOffset, length2 + 12, 1, 1015, 0, '/ML=256');

  DlgAddCtrl(ddlg, Dlg_GroupBox, ' Hardware Information ', 0, Dlg_PosOffset | 1, 104, Dlg_Units | 53, 1017, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Machine Mfr:', column1, Dlg_PosOffset | 1, 0, 0, 1020, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, Mfr, column2, Dlg_PosOffset, length1, 1, 1025, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'CPU type and spd:', column3, Dlg_PosOffset, 0, 0, 1030, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, CPU, column4, Dlg_PosOffset, length2, 1, 1035, 0, '');

  DlgAddCtrl(ddlg, Dlg_Static, 'Video Card:', column1, Dlg_PosOffset | 1, 0, 0, 1040, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, VCard, column2, Dlg_PosOffset, length1, 1, 1045, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Memory Avail:', column3, Dlg_PosOffset, 0, 0, 1050, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, MAvail, column4, Dlg_PosOffset, length2, 1, 1055, 0, '');

  DlgAddCtrl(ddlg, Dlg_Static, 'Network Type:', column1, Dlg_PosOffset | 1, 0, 0, 1105, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, NetType, column2, Dlg_PosOffset, length1, 1, 1110, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Network Version:', column3, Dlg_PosOffset, 0, 0, 1115, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, NetVer, column4, Dlg_PosOffset, length2, 1, 1120, 0, '');

  DlgAddCtrl(ddlg, Dlg_GroupBox, ' Software Information ', 0, Dlg_PosOffset | 2, 104, Dlg_Units | 50, 1060, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Operating System:', column1, Dlg_PosOffset | 1, 0, 0, 1065, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, OS, column2, Dlg_PosOffset, length1, 1, 1070, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'MEW Version:', column3, Dlg_PosOffset, 0, 0, 1075, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, version, column4, Dlg_PosOffset, length2, 1, 1080, DLGF_Disable, '');

  DlgAddCtrl(ddlg, Dlg_Static, 'MEW Install Dir:', column1, Dlg_PosOffset | 1, 0, 0, 1085, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, me_path, column2, Dlg_PosOffset, length1, 1, 1090, 0, '');
  DlgAddCtrl(ddlg, Dlg_Static, 'Command Map:', column3, Dlg_PosOffset, 0, 0, 1095, 0, '');
  DlgAddCtrl(ddlg, Dlg_Text, global_str('&WCMDMAPNAME'), column4, Dlg_PosOffset, length2, 1, 1100, DLGF_Disable, '');

  DlgAddCtrl(ddlg, Dlg_CheckBox, 'MEW Install Dir is a Network Drive', column1, Dlg_PosOffset | 1, 0, 0, 1105, 0, '');
  DlgSetInt(ddlg, 1105, MEWNet);
  DlgAddCtrl(ddlg, Dlg_CheckBox, 'Enhanced Brief Mode', column3, Dlg_PosOffset, 0, 0, 1110, DLGF_Disable, '');
  DlgSetInt(ddlg, 1110, global_int('&BriefMode'));

  DlgAddCtrl(ddlg, Dlg_PushButton, 'OK', 40, Dlg_PosOffset | 2, Dlg_StanBtnWidth, 1, 1500, 0, '/R=1');
  DlgAddCtrl(ddlg, Dlg_PushButton, 'Cancel', 55, Dlg_PosOffset, Dlg_StanBtnWidth, 1, 1501, 0, '/R=0');

  /* Execute the dialog, and if the user presses OK, save the dialog information into globals */
  if ( DlgExecute(ddlg, 1005, 'Bug Report User Info', '', '', 0) )
  {
    Name = DlgGetStr(ddlg, 1005);
    Email = DlgGetStr(ddlg, 1015);
    Mfr = DlgGetStr(ddlg, 1025);
    CPU = DlgGetStr(ddlg, 1035);
    VCard = DlgGetStr(ddlg, 1045);
    MAvail = DlgGetStr(ddlg, 1055);
    NetType = DlgGetStr(ddlg, 1110);
    NetVer = DlgGetStr(ddlg, 1120);
    OS = DlgGetStr(ddlg, 1070);
    MEWNet = DlgGetInt(ddlg, 1095);
    DlgKill(ddlg);                               // Kill the dialog
    return(1);                                   // Return 1 because the user pressed OK
  }
  else
  {
    DlgKill(ddlg);
    return(0);                                   // Return 0 because the user did not press OK
  }
}


int saveuserinfo()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: saveuserinfo

Description:  Takes the user information stored in global variables and saves
              it to a .DB file

Returns: 1 if info was saved successfully
         0 if info was not saved

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  str gn;
  /* First, we open the DB file.  If it doesn't exist, create it */
  if( LocateDBPage( dbfilename, dbpagename, 1 ) )
	{
    /* If the DB file is read only */
		if( read_only )
		{
      /* Make a message that the DB file is locked and abort the macro */
      rm("MESSAGEBOX /B=2/T=Error Saving Configuration/M="+dbfilename+" is locked!");
      return(0);
    }
    /* This code below is borrowed from macro SETSAVE MEWSETUP.S  I didn't examine how it works */
    int tl = c_line;
		goto_col(1);
		down;
		block_begin;
		while(!at_eof && (cur_char != "\f"))
		{
			down;
		}
		up;
		block_end;
		if(c_line > tl)
			delete_block;
		goto_line(tl);

		eol;
    cr;

    Gn = "!BugRepName";
    call Do_Global_Str;
    Gn = "!BugRepEmail";
    call Do_Global_Str;
    Gn = "!BugRepMfr";
    call Do_Global_Str;
    Gn = "!BugRepCPU";
    call Do_Global_Str;
    Gn = "!BugRepVCard";
    call Do_Global_Str;
    Gn = "!BugRepMAvail";
    call Do_Global_Str;
    Gn = "!BugRepNetType";
    call Do_Global_Str;
    Gn = "!BugRepNetVer";
    call Do_Global_Str;
    Gn = "!BugRepOS";
    call Do_Global_Str;
    Gn = "!BugRepMEWNet";
    call Do_Global_Int;

    save_file;
    return(1);
  }
  else
	{
    /* Since the DB file or DB page name was not found, display an error message and abort */
    rm("MESSAGEBOX /B=2/T=Error Saving Configuration/M=Could not find "+dbpagename+" in "+dbfilename+"!");
    return(0);
  }

/* These two call procedures were also borrowed from SETSAVE */

do_global_str:
	put_line("/GS=" + gn + "=" + Convert_String( global_str(gn)));
	eol; cr;
	ret;

do_global_int:
	put_line("/GI=" + gn + "=" + str( Global_Int(gn)));
	eol; cr;;
	ret;
}


int loaduserinfo()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: loaduserinfo

Description:  Opens up the user info .DB file and loads the information into
              global variables.

Returns: 1 if user info was loaded correctly
         0 if user info was not loaded correctly

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  int tempint;
  str tempstr, tempstr2;
  /* If the DB file exists, load it, otherwise go to the else below */
  if( LocateDBPage( dbfilename, dbpagename, 0 ) )
  {
    down;
    goto_col(1);
    /* The do...while loop below parses out sections of each line, determines whether
       the line stores a global string or global integer variable, gets the variable
       name, and sets that global with the appropriate value */
    do
    {
      /* If the line is a global string */
      if ( get_word('=') == '/GS' )
      {
        right;
        tempstr = get_word('=');
        right;
        set_global_str(tempstr, reconvert_string(get_word('')));
      }
      /* The line is a global integer */
      else
      {
        right;
        tempstr = get_word('=');
        right;
        val(tempint, get_word(''));
        set_global_int(tempstr, tempint);
      }
      down;
      goto_col(1);
    } while ( !at_eof && (cur_char != "\f") );
  }
  else
	{
    /* The DB file could not be found, or the DB page could not be found, display an error
       message and abort the macro */
    rm("MESSAGEBOX /B=2/T=Error Loading Configuration/M=Could not find "+dbpagename+" in "+dbfilename+"!");
    return(0);
  }
  return(1);                                     // Return 1 because the info load was successful
}


int checkuserinfo()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: checkuserinfo

Description:  Loads the user info .DB file and checks to see if the name field
              is blank

Returns: 0 if the user name is blank or there was an error locating the DB page/file
         1 if the user name is set

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  /* Look for the DB file and load it.  If it doesn't exist, go to the else, below */
  if( LocateDBPage( dbfilename, dbpagename, 0 ) )
  {
    down;
    /* Check the first record of the DB and see if the user name global entry is blank */
    if ( remove_space(get_line) == '/GS=!BugRepName=')
    {
      /* If it is, return 0 - indicating user name is not set*/
      return(0);
    }
  }
  else
  {
    /* If the DB file could not be found, or there was an error in it, abort with an error message */
    rm("MESSAGEBOX /B=2/T=Error Scanning Configuration/M=Could not find "+dbpagename+" in "+dbfilename+"!");
    return(0);
  }
  return(1);                                     // Return 1, the user name has been set
}


void buildbugrep()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: buildbugrep

Description:  Creates a window and builds the bug report form in it.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  /* If we have already build the bug report window once, then don't do it again */
  if ( !BuiltOnce )
  {
    str tempstr;
    int oldim = insert_mode, tempint, jx;
    insert_mode = 1;
    /* Create the bug report output window, and put the text into it.
       We use the values of the globals to fill in the user information */
    create_window;
    OutWin = window_id;
    goto_col(15);
    text('Multi-Edit for Windows Bug Report Form (ver 1.2)');
    cr;cr;
    jx = 3;
    if ( !(Desc == '') )
    {
      text('Problem: '+Desc);
      cr;
      cr;
      jx += 2;
    }
    if ( !(Number == '') )
    {
      text('Error number/address: '+Number);
      cr;
      cr;
      jx += 2;
    }
    /* Here we switch to the window containing the 'steps to create the bug' and use
       put_line_to_win to put the contents of this window into our output window.
       I tried using a block copy operation, but couldn't get it to work correctly */
    tempint = cur_window;
    switch_win_id(RepWin);
    tof;
    put_line_to_win(get_line, jx++, tempint, 0);
    if ( !at_eof )
    {
      do
      {
        down;
        put_line_to_win(get_line, jx++, tempint, 0);
      } while ( !at_eof );
    }
    switch_win_id(OutWin);
    eof;
    cr;
    text('----------------------------------------------------------------');
    cr;
    text('Name: '+Name);
    goto_col(38);
    text('Email Addr: '+Email);
    cr;
    cr;
    if ( !(Mfr == '') )
    {
      tempstr = 'Machine: '+Mfr;
      if ( !(CPU == '') )
      {
        tempstr = tempstr + ' '+CPU;
      }
      if ( !(MAvail == '') )
      {
        if ( xpos('M', MAvail, 1) )
        {
          tempstr = tempstr + ' '+MAvail;
        }
        else tempstr = tempstr + ' '+MAvail+' Mb';
      }
      text(tempstr);
      cr;
    }
    if ( !(VCard == '') )
    {
      text('Video Card: '+VCard);
      cr;
    }
    if ( !(NetType == '') )
    {
      tempstr = 'Network: '+NetType;
      if ( !(NetVer == '') )
      {
        tempstr = tempstr + ' ver '+ NetVer;
      }
      text(tempstr);
      cr;
    }
    cr;
    text('Version: '+version);
    if ( !(OS == '') )
    {
      goto_col(38);
      text('OS: '+OS);
    }
    cr;
    text('Install Dir: '+me_path);
    goto_col(38);
    text('Network Drive: ');
    if ( MEWNet )
    {
      text('YES');
    }
    else text('NO');
    cr;
    text('Command Map: '+global_str('&WCMDMAPNAME'));
    goto_col(38);
    text('Enhanced Brief Mode: ');
    if ( global_int('&BriefMode') )
    {
      text('YES');
    }
    else text('NO');
    cr;
    insert_mode = oldim;
    BuiltOnce = 1;       // We've built this window once now, so set this global
  }
}


void bugrepcopy()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: bugrepcopy

Description:  Copies the bug report form to the Windows clipboard to allow a user
              to paste it in an email message.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  /* Switch to the output window, block the whole window, and run the cut macro
     to copy the contents to the buffer */
  switch_win_id(OutWin);
  tof;
  block_begin;
  eof;
  block_end;
  rm('meutil2^cut /O=1');
}


void bugrepprint()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: bugrepprint

Description:  Prints a hard copy of the bug report.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  printwindow(frame_handle, cur_window);         // Frame_handle is a system variable
}


void bugrepsave()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: bugrepsave

Description:  Saves the bug report to a file.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  rm('savefile');
}


void getbugreport()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: getbugreport

Description:  Creates a dialog with fields describing the bug that the user
              is reporting.  From this dialog, users can print, copy to clipboard,
              or save the bug report.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  int rdlg, cdlg, tempint;
  create_window;
  RepWin = window_id;
do_again:                                        // This label is so we can loop back and rebuild the dialog
  /* Create the dialog and define the controls we have in it */
  DlgCreate(rdlg);
  DlgAddCtrl(rdlg, Dlg_Static, 'Give a brief description of the problem:', 1, 1, 0, 0, 1000, 0, '');
  DlgAddCtrl(rdlg, Dlg_Text, Desc, 1, Dlg_PosOffset | 1, 100, 1, 1005, 0, '');
  DlgAddCtrl(rdlg, Dlg_Static, 'If there is an error number or GPF/Exception 13 address, please list it:', 1, Dlg_PosOffset | 2, 0, 0, 1020, 0, '');
  DlgAddCtrl(rdlg, Dlg_Text, Number, 70, Dlg_PosOffset, 31, 1, 1025, 0, '');
  DlgAddCtrl(rdlg, Dlg_Static, 'Please give a description, or steps if possible, to recreate the problem:', 1, Dlg_PosOffset | 2, 0, 0, 1010, 0, '');
  DlgAddCtrl(rdlg, Dlg_Text, '', 1, Dlg_PosOffset | 1, 100, 11, 1015, DLGF_GetTextFromWin | DLGF_es_MultiLine | DLGF_es_WantReturn, "/ML=32000/WID="+str(RepWin));
  DlgAddCtrl(rdlg, Dlg_PushButton, 'Close', 1, 19, Dlg_StanBtnWidth, 1, 1100, 0, '/R=1');
  DlgAddCtrl(rdlg, Dlg_PushButton, '&Copy to Clipboard', 14, Dlg_PosOffset, 20, 1, 1200, 0, '/R=100');
  DlgAddCtrl(rdlg, Dlg_PushButton, '&Print Hardcopy', 36, Dlg_PosOffset, 20, 1, 1205, 0, '/R=200');
  DlgAddCtrl(rdlg, Dlg_PushButton, '&Save to File', 58, Dlg_PosOffset, 20, 1, 1210, 0, '/R=300');
  DlgAddCtrl(rdlg, Dlg_PushButton, 'Change &User Info', 80, Dlg_PosOffset, 20, 1, 1215, 0, '/R=400');
  tempint =  DlgExecute(rdlg, 1005, 'Bug Report Information Form', '', '', 0);
  /* If the user pressed any of the buttons besides Close */
  if ( tempint > 99 )
  {
    /* Get the information out of the two single line text fields and kill the dialog */
    Desc = DlgGetStr(rdlg, 1005);
    Number = DlgGetStr(rdlg, 1025);
    DlgKill(rdlg);
    switch ( tempint )
    {
      case 100 :
        buildbugrep();
        bugrepcopy();
        goto do_again;                           // Go back and rebuild the dialog
      case 200 :
        buildbugrep();
        bugrepprint();
        goto do_again;
      case 300 :
        buildbugrep();
        bugrepsave();
        goto do_again;
      case 400 :
        if ( getuserinfo())                      // Bring up the user info dialog
        {
          saveuserinfo();                        // If OK is pressed, then save the user info
        }
        goto do_again;
      default:
        goto do_again;                           // then just rebuild the dialog
    }
  }
  DlgKill(rdlg);                                 // If the user presses close or cancel,
}                                                // then just kill the dialog and exit


void bugrepcleanup()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: bugrepcleanup

Description:  Cleans up the globals created that store the user information.
              Also switches to the bug report window and the description window
              and deletes them.

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  /* Here we just set all the globals we used back to null or 0, thus removing them from memory */
  name = '';
  email = '';
  mfr = '';
  cpu = '';
  vcard = '';
  MAvail = '';
  nettype = '';
  netver = '';
  os = '';
  mewnet = 0;
  desc = '';
  number = '';
  builtonce = 0;
  /* Switch to the windows we created, and delete them */
  /* If for some reason they didn't get created, don't delete any windows,
     but set the globals to 0 in any case */
  if ( switch_win_id(repwin))
  {
    delete_window;
  }
  repwin = 0;
  if (  switch_win_id(outwin))
  {
    delete_window;
  }
  outwin = 0;
}


void bugrep()
/*******************************************************************************
																MULTI-EDIT MACRO

Name: bugrep

Description:  The main bug report macro.  This is the one to run!

               (C) Copyright 1995 by American Cybernetics, Inc.
*******************************************************************************/
{
  int start_win = window_id,                     // Save the current window
      oldrm = refresh;                           // and the current refresh state
  refresh = 0;
  if ( !checkuserinfo() )                        // If user name is not set
  {
    loaduserinfo();                              // Load the defaults
    if ( getuserinfo() )                         // Get the user info
    {
      if ( saveuserinfo() )                      // Save the user info
      {
        getbugreport();                          // Get the bug report
      }
    }
  }
  else                                           // The user name is set
  {
    if ( loaduserinfo() )                        // Load the user's info
    {
      getbugreport();                            // Get the bug report
    }
  }
  bugrepcleanup();                               // Clean up the globals we set and delete extra windows
  switch_win_id(start_win);                      // Switch back to the original window
  refresh = oldrm;                               // Restore refresh state
}
