#include<stdio.h> 
#include<string.h> 
/* 




                 VV                   VV    EEEEEEEEEEEEEE   
                  VV                 VV     EE  
                   VV               VV      EE
                    VV             VV       EE
                     VV           VV        EE
                      VV         VV         EEEEEEEEEEEEEE
                       VV       VV          EE
                        VV     VV           EE
                         VV   VV            EE
                          VV VV             EE
                           VVV              EE
                            V               EEEEEEEEEEEEEE
                                                       
 
 
 
 
                       MODULE  : jumpcmd.c
 
                       VERSION : v3.5
 
                       REVISED : 30 Jun 2005
 
                       AUTHOR  : Michael A. Campbell
 
 
 
 
 
 


                          FUNCTIONAL DESCRIPTION
                          ----------------------
 
               This module contains the jump commands and the tag  
 
               commands for the VE editor. These allow the editor to 
               
               jump to the top or bottom of a file, to any line number 
               
               in between, or to set and jump to user specified tags.
 









*/

/* .page */

/*****************
 * INCLUDE FILES *
 *****************/

#include <curses.h>

#include "../def/common.def"
#include "../def/kbdif.def"

#include "../str/vestruct.str"


#include "../inc/vedbase.inc"
#include "../inc/termif.inc"


#include "../ext/veutils.ext"
#include "../ext/termif.ext"
#include "../ext/kbdif.ext"
#include "../ext/lnklst.ext"
#include "../ext/jumpcmd.ext"

/* .page */

void list_tags ()

/****************************************************************************
 *                                                                          *
 * This function performs a full screen listing of the available tags.      *
 *                                                                          *
 ****************************************************************************/

begin
    register int i, len;   /* Simple loop counter, string length            */
    char msg_buf[82];      /* For building the output lines                 */

    create_full_screen_info_page ( " - Tags Listing" );

    /* Tag field at 0, LineNumber Field at 8 */

    mv_writestr ( 0, 3, FALSE, "Tag     LineNum" );

    for ( i = 0; i <= 9; i++ ) begin

       sprintf ( msg_buf, "%d      %d", i, curr_file.tags[i] );

       if ( curr_file.tags[i] == 0 ) begin

          /* If the tag value is zero, the tag is undefined - user line nums */
          /* in VE start at 1. So, truncate the '0', and put "Undefined" in  */
          /* its place.                                                      */

          len = strlen(msg_buf);
          msg_buf[len-1] = '\0';
          strcat ( msg_buf, "Undefined" );
       end

       mv_writestr ( 1, 5+i, FALSE, msg_buf );

    end /* for */

    remove_full_screen_info_page ();

end /* list_tags */

/* .page */

void jump_to_tag ()

/****************************************************************************
 *                                                                          *
 *   This function prompts for a tag and then jumps to that tag. It is      *
 *   called from the tags_cmd and jump_to_tag_cmd routines.                 *
 *                                                                          *
 ****************************************************************************/

begin
   char selection;           /* The user's tag number selection             */
   int line_num;             /* The line number for the tag                 */
   int actual;               /* The actual number of lines moved            */
   char result_msg [40];     /* For building result messages                */

   /* Prompt for a tag number */

   write_status_line ( "Enter tag number: " );
   selection = read_char ();

   if ( selection >= '0' && selection <= '9' ) begin

      /* Valid tag number entered */

      line_num = curr_file.tags[selection - '0'];

      if ( line_num == 0 ) begin
         strcpy ( result_msg, "Tag x not defined" );
         result_msg[4] = selection;
         write_ve_msg ( result_msg );
      end

      else begin

         /* Valid tag: jump to it */

         curr_line = traverse_list (&curr_file, curr_file.head, '+', &actual, 
                                    line_num - 1, &status);
         display_new_screen ( curr_screen.cx );

         curr_line_num = line_num - 1;
         display_curr_position ();
      end

   end /* valid tag number */

   else
      write_ve_msg ( "Not a valid tag number" );

end /* jump_to_tag */

/* .page */

void tags_cmd ()

/****************************************************************************
 *                                                                          *
 *   The Tags command allows a user to set, clear and list tags, which are  *
 *   a way of marking a line so that you can later jump to it.              *
 *                                                                          *
 *   Note that this is a simple line number based approach. It remembers    *
 *   the line number that the cursor is on. If the user adds or subtracts   *
 *   lines from the file and then jumps to a previous tag, they may not end *
 *   up on the expected line.                                               *
 *                                                                          *
 ****************************************************************************/

begin
   char selection;              /* The user's menu selection                */
   register int i;              /* A simple loop counter                    */
   int line_num;                /* Line number for a tag                    */
   int num_lines;               /* Number of lines in the file              */
   int actual;                  /* Actual number of lines moved             */
   struct node *cnode;          /* A line in the file                       */
   char result_msg [40];        /* For building result messages             */

   char tags_menu [] = "0-9  Clear  List  Jump : ";

   update_curr_line ();

   push_status_line ( tags_menu );

   selection = toupper (read_char ());  /* Read the users selection         */

   if ( selection >= '0' && selection <= '9' ) begin
   
      /* Define the current line's number as the indicated tag.             */

      curr_file.tags[selection - '0'] = get_curr_line_num () + 1;

      strcpy ( result_msg, "Tag x set" );
      result_msg[4] = selection;
      write_ve_msg ( result_msg );

   end /* selection is 0-9 */

   
   else if ( selection == 'C' ) begin

      /* Clear all tags */

      for ( i = 0; i <= 9; i++ )
         curr_file.tags[i] = 0;

      write_ve_msg ( "All tags cleared" );

   end /* Clear all tags */


   else if ( selection == 'L' ) begin

      /* List all currently defined tags */

      list_tags ();

   end /* List all tags */


   else if ( selection == 'J' ) begin

      /* Jump to a tag */
      
      jump_to_tag ();

   end /* Jump to tag */


   else if ( selection != ENTER ) begin

      /* Invalid selection - beep and write an error message. ENTER is  */
      /* allowed as a "do nothing and exit this menu" command.          */

      writechar ( BEL );
      write_ve_msg ( invalid_msg );

   end /* invalid selection */

   pop_status_line ();

end /* tags_cmd */

/* .page */

void jump_to_tag_cmd ()

/****************************************************************************
 *                                                                          *
 *   The JumpToTag command prompts for a tag number to jump to, and then    *
 *   jumps to the line number indicated by the tag.                         *
 *                                                                          *
 ****************************************************************************/

begin

   update_curr_line ();

   push_status_line ( " " );  /* Nil push - saves current status line       */

   jump_to_tag ();

   pop_status_line ();        /* Restore previous status line               */

end /* jump_to_tag_cmd */

/* .page */

void jump_cmd ()

/*****************************************************************************
 *                                                                           *
 *   Jump to one of the start of the file, the end of the file, or a line    *
 *   within the file.                                                        *
 *                                                                           *
 *****************************************************************************/

begin
    int actual, line;     /* For linked list traversals                      */
    char selection;       /* Menu selection                                  */

    char jump_menu [] = "Start  End  Line  Tag : ";

    update_curr_line ();   /* Update the current line before leaving it.     */

    /* Clear the status line, and output a prompt                            */

    push_status_line ( jump_menu );

    selection = toupper (read_char ());  /* Read the users selection         */


    if (selection == 'S') begin          /* Jump to start of file            */
        curr_line = curr_file.head;
        curr_line_num = 1;
    end


    else if (selection == 'E') begin     /* Jump to end of file              */
        bottom_of_file_cmd ();
        pop_status_line ();
        return;
    end


    else if (selection == 'L') begin     /* Jump to a line within the file   */

        line = 1;                        /* Default if all else fails        */

        temp.length = prompt_read_str ( 0, 0, "Line: ", -1, -1, temp.text, 12 );
        if ( temp.length > 0 )
           sscanf (temp.text, "%d", &line);

        if (line == 0) then                  /* Lines start at 1 for user,   */
            line = 1;                        /* but at 0 for VE              */

        curr_line = traverse_list (&curr_file, curr_file.head, '+', &actual, 
                                   line - 1, &status);
        curr_line_num = actual + 1;
    end

    else if ( selection == 'T' ) then
       jump_to_tag ();

    else if ( selection != ENTER ) then
        writechar ( BEL );

    display_new_screen ( curr_screen.cx );

    if ( selection == 'S' || selection == 'E' || selection == 'L' ) then
       display_curr_position ();

    pop_status_line ();

end /* jump_cmd */

/* .page */

void top_of_file_cmd ()

/****************************************************************************
 * This function moves the screen to the top of the file. It is analagous   *
 * to the J(ump S(tart command, and exists as a separate command so that it *
 * can be bound to a keyboard command, yielding an accelerated version of   *
 * the JumpStart command. This function returns no value.                   *
 ****************************************************************************/

begin
    update_curr_line ();

    curr_line = curr_file.head;
    curr_line_num = 1;

    display_new_screen ( curr_screen.cx );
    display_curr_position ();

end /* top_of_file_cmd */

/* .page */

void bottom_of_file_cmd ()

/****************************************************************************
 * This function moves the screen to the bottom of the file. It is like the *
 * J(ump E(nd command, and exists as a separate command so that it can be   *
 * bound to a keyboard command, yielding an accelerated version of the      *
 * the JumpEnd command. This function returns no value.                     *
 ****************************************************************************/

begin
    int cy;
    int actual, status;

    update_curr_line ();

    if ( displayed(curr_file.tail, &cy))
    begin
       curr_line      = curr_file.tail;
       curr_line_num  = curr_file.nodes;
       curr_screen.cy = cy;

       display_curr_position ();
       restore_cursor ();
    end
    
    else
    begin
       /* display_new_screen attempts to place the current line at line 11  */
       /* of the screen. To provide an end of file display that has a few   */
       /* lines of blanks at the end of the display, but shows most of the  */
       /* page at the end of file, we make the current line the one that is */
       /* one screen full back from the bottom minus 15. This leaves 4      */
       /* blank lines at the bottom of the screen.                          */

       curr_line = traverse_list (&curr_file, curr_file.tail, '-', &actual,
                                  physical_lines - 15, &status);

       curr_screen.cy = update_curr_screen (11);
       draw_curr_screen ();

       /* Finally, we recursively call ourselves. The last line of the file */
       /* is now on screen and this causes the first part of the            */
       /* if-then-else above to execute, moving the cursor to the last line */
       /* of the screen.                                                    */

       bottom_of_file_cmd ();

    end

end /* bottom_of_file_cmd */

