macro_file Nuzletr;

/*************************************************************************
																	SUMMARY
Winter 91-92      Vol 1, Number 1
	HDI - How to search for Control Characters
				How to keep text from changing colors when changed.
				How can ME restore previous session
				How to get the DOS shell to display in condensed form always

	LKF - N/A

	MLL - N/A

Summer 92			 		Vol 2, Number 1
	HDI - How to interface to a compiler or program that requires EMS/XMS.
				How to compile using batch file without running out of env. space

	LKF - SETUP^KEYCODE

	MLL - Backspace macro

Fall 92						Vol 2, Number 2
	HDI - How to get ME to use spaces instead of tabs
				How to remember the print margins in the print dialog box

	LKF - Default filename extensions when loading a file

	MLL - Cusror macros (Left, right, up, down)

Winter 93					Vol 3, Number 1
	HDI - How to modify reserved words for Syntax highlighting
				How to change the colors of the MEERR.TMP window

	LKF - The /L command line option

	MLL - Incremental Search macro

Spring 93					Vol 3, Number 2
	HDI - How do I create a prompt for user input when writing a macro

	LKF - N/A

	MLL - Fastcursor macro

Fall 93						Vol 3, Number 3
	HDI - How do I get key assignments to appear next to user menu options
				How do I turn off EOF marker

	LKF - Arcdir command and Zipdir command Global variables

	MLL - Flip Anchor and Extend Block Macros

Winter 94					Vol 4, Number 1
	HDI -
				Q:  When I edit in hex mode, I can't see control characters.  Namely,
				    CR,LF.

				A: Load the file as a binary file and set the Binary record length to
				   16.  This will give Multi-Edit the appearance of more traditional
				   hex editors.

				Q:  Is there a way to mark a block of text and have that text appear
						as my search string in a Search Dialog box?

				A:  Yes.  Mark the text then bring up the Search dialog box.  Access
						the history list by either pressing the down arrow or the space
						bar, depending on the interface you're using.  You'll notice that
 						the marked text is the first item to	appear in the history list.
						Now, hilight and select the text.
						NOTE:  This does not work for Columnar Blocks.

	LFK -

	Some of you may have noticed that when clicking and holding the mouse on
  the arrows in a scrollbar, Multi-Edit will scroll at a normal rate initially
	but then the scroll rate becomes very rapid.   If you wish for the
	scrolling rate to be slower, try using the @MOU_SCRL_BAR_DELAY Global
	variable.  To use this, you must be using version 7.0 or greater.  Load the
	\ME\SRC\STARTUP.S file into Multi-Edit and within the body of the macro, add
	the following line.

								Set_Global_Int("@MOU_SCRL_BAR_DELAY",50)

	The value of 50 is the delay in milliseconds to provide a constant scroll
	rate.  This value can be set to anything greater than zero.  All that's left
	to do is compile this source code, exit, and re-start Multi-Edit.

	MLL - Scroll Region macros (up, down)
***************************************************************************/


// Fall Newsletter '93

/* These two handy macros provide you with the ability to either extend a
   marked block or simply flip the anchor of a block.  This allows you to
   easily include a line or column that you may have inadvertently left out
   of a marked block.
*/

macro FlipAnchor Trans2 {
  int NewFreePointL,NewFreePointC,OldRefresh=Refresh,WinBottom=(Win_Y2-Win_Y1)-1,
      opb = persistent_blocks;
  persistent_blocks = true;

  if ( Block_Stat ) {             // If a block is marked
    Refresh=False;                // Turn screen refresh off
    if ( C_Col==Block_Col1 ) {    // If we are at the left margin of a block
      Block_ColX=Block_Col1;
      NewFreePointC=Block_Col2;
    }
    else {
      Block_ColX=Block_Col2;
      NewFreePointC=Block_Col1;
    }
    if ( C_Line==Block_Line1 ) {  // If the current line is at the top of the block
      Block_LineX=Block_Line1;
      NewFreePointL=Block_Line2;
      while ( (C_Row<WinBottom) && (C_Line!=NewFreePointL) )  // Go down untill we're either
        Down;                     // at the bottom of the screen or the other end of the block
      if ( 3==Block_Stat )        // If this is a stream block
        NewFreePointC++;          // Increment the NewFreePointC variable
    }
    else {
      Block_LineX=Block_Line2;
      NewFreePointL=Block_Line1;
      while ( (C_Row>1) && (C_Line!=NewFreePointL) )  // Go up untill we're at the top
        Up;                        // of the screen or the other end of the block
    }
    Goto_Line(NewFreePointL);      // Goto the other end of the block
    if ( 1!=Block_Stat )           // If we're not using a line block
      Goto_Col(NewFreePointC);     // place the cursor at the correct column

    Marking=True;                  // Turn marking on
    Refresh=OldRefresh;
    Redraw;
    }
  else
    Make_Message('No block marked.');  // Otherwise tell the user that a block isn't marked
    persistent_blocks = opb;
}


macro ExtendBlock Trans2 {
  if ( !Marking && Block_Stat ) {    // Make sure we ended our block mark
    int dl1=C_Line-Block_Line1,dl2=C_Line-Block_Line2, // Initialize variables
        dc1=C_Col-Block_Col1,dc2=C_Col-Block_Col2;

    if ( dl1<0 ) dl1= -dl1;          // Make sure all the values are positive
    if ( dl2<0 ) dl2= -dl2;          // so we can run accurate comparisons later
    if ( dc1<0 ) dc1= -dc1;
    if ( dc2<0 ) dc2= -dc2;

    if ( dl1<dl2 ) {                 // If we're before the beginning of the block
      Block_Line1=C_Line;            // extend the block to the current line
      if ( 3==Block_Stat )           // If this  is a stream block
        Block_Col1=C_Col;            // extend the block column to the proper position
      else if ( 2==Block_Stat )      // If this is a columnar block
        if ( dc1<dc2 )               // and if we're before the beginning of the block
          Block_Col1=C_Col;          // extend the block to the current column
        else                         // Otherwise, we're past the end of the block, so
          Block_Col2=C_Col;          // extend the block out that way.
    }
    else {
      Block_Line2=C_Line;            // Extend the block past the end to the current line
      if ( 3==Block_Stat )           // If this is a stream block
        Block_Col2=C_Col;            // extend the block column to the proper position
      else if ( 2==Block_Stat )      // If this is a columnar block
        if ( dc1<dc2 )               // and if we're before the beginning of the block
          Block_Col1=C_Col;          // extend the block to the current column
        else                         // Otherwise, we're past the end of the block, so
          Block_Col2=C_Col;          // extend the block out that way.
    }
  }
  Redraw;                            // Redraw the screen
}


// February '94

void PROCESS_DOS_ERR(int Dos_Error) {
  error_level = 3000 + dos_error;
  RM("MEERROR");
}

void LASTLINE() {
/* finds last line of file and allows editing in a dialog box.  For big files
   where you don't want to wait to get to the bottom just to edit the last
   line */

  int dos_error, handle = 0, file_pointer_offset, file_buf_length;

  str t_line_terminator[2], file_buf[2048], t_file_name[128];

  return_str = "";
  RM("file_prompt /FTO=1/NHA=1/T=ENTER FILE TO EDIT THE LAST LINE OF");
  if (return_int) {
    switch (global_int("!FILE_TYPE_OVERRIDE")) {
      case 3 :
        RM("MESSAGEBOX /B=2/M=Binary files not supported.");
        RETURN();
        break;
      case 2 :
        t_line_terminator = "\x0A";
        break;
      default:
        t_line_terminator = "\x0D\x0A";
        break;
    }

    t_file_name = caps(return_str);
    if (dos_error = s_open_file(t_file_name,0x12,handle)) {
			PROCESS_DOS_ERR(Dos_Error);
      RETURN();
    } else {
      if (dos_error = s_move_file_ptr(handle,2,0)) {  // move to end of file
		 		PROCESS_DOS_ERR(Dos_Error);
      } else {
/* read the file backwards and find the first occurance of a char that is not
   a line terminator, nor a ^Z */
        file_pointer_offset = -1;
        do {
          if (dos_error = s_move_file_ptr(handle,2,file_pointer_offset)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          if (dos_error = s_read_bytes(file_buf,handle,1)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          --file_pointer_offset;
        } while (xpos(file_buf,"\x1A" + t_line_terminator,1));

// find the next (previous) line terminator
FIND_LINE_TERM:
        do {
          if (dos_error = s_move_file_ptr(handle,2,file_pointer_offset)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          if (dos_error = s_read_bytes(file_buf,handle,1)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          --file_pointer_offset;
        } while (file_buf != str_char(t_line_terminator,svl(t_line_terminator)));

        if (svl(t_line_terminator) == 2) {
          if (dos_error = s_move_file_ptr(handle,2,file_pointer_offset)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          if (dos_error = s_read_bytes(file_buf,handle,1)) {
						PROCESS_DOS_ERR(Dos_Error);
            goto ABORT;
          }
          if (file_buf != str_char(t_line_terminator,1)) { // keep looking
            --file_pointer_offset;
            goto FIND_LINE_TERM;
          }
        }

        file_pointer_offset = file_pointer_offset + svl(t_line_terminator);
/* Now, we are ready to read in the line.  We'll include any trailing line
   terminators and ^Z's
*/
        if (dos_error = s_move_file_ptr(handle,2,file_pointer_offset)) {
					PROCESS_DOS_ERR(Dos_Error);
          goto ABORT;
        }
        if (dos_error = s_read_bytes(file_buf,handle,0 - file_pointer_offset)) {
					PROCESS_DOS_ERR(Dos_Error);
          goto ABORT;
        }

// put it in a prompt
        return_str = file_buf;
        RM("QUERYBOX /ML=2048/T=EDITING THE LAST LINE OF " +
          truncate_path(t_file_name) + "/W=" + str(screen_width - 9));
        if (return_int) {
          file_buf = return_str;
          RM("VERIFY /T=Save changes?");
          if (return_int) {
            if (dos_error = s_move_file_ptr(handle,2,file_pointer_offset)) {
							PROCESS_DOS_ERR(Dos_Error);
              goto ABORT;
            }
            if (dos_error = s_write_bytes(file_buf,handle,file_pointer_offset)) {
							PROCESS_DOS_ERR(Dos_Error);
              goto ABORT;
            } else if (file_pointer_offset != svl(file_buf)) { // disk full
              error_level = 3241;
              RM("MEERROR");
              goto ABORT;
            }
// adjust file size for new line
            if (dos_error = s_write_bytes("",handle,file_pointer_offset)) {
							PROCESS_DOS_ERR(Dos_Error);
              goto ABORT;
            }
          }
        }
      }
    }
  }

ABORT:
  if (handle > 0) {
    if (dos_error = s_close_file(handle)) {
			PROCESS_DOS_ERR(Dos_Error);
    }
  }
}

/*At times, users may want to scroll up or scroll down but have the
ability to see a few lines beyond the current line.  The following
macros allow you to define an upper and lower boundary where text will
be visible before or after the current line.  The number 2 in the
#define statements is a good starting number.  You can change it as you
see fit.
*/

#define UPPER_BOUNDARY 2
#define LOWER_BOUNDARY 2

void SCROLL_REGION_UP() {
  if (c_row <= UPPER_BOUNDARY) {
    RM("SCROLLDN");
  } else {
    up;
  }
}

void SCROLL_REGION_DN() {
  if (c_row >= ((win_y2 - win_y1 - 1) - LOWER_BOUNDARY)) {
    RM("SCROLLUP");
  } else {
    down;
  }
}


/*
It is recommended that you assign these macros to your <Up> and <Down>
keys.  This macro will not cover all cursor movements.  If you are
ambitious, try creating the same for <PgUp> and <PgDn>.  You can even
integrate this logic in the Searching routines if you have the
Professional Version of Multi-Edit.

NOTE: The C Style macro definitions can be used in version 7.0 or
			greater only.
*/
