home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR8 / TDE32.ZIP / UTILS.C < prev    next >
C/C++ Source or Header  |  1993-11-13  |  84KB  |  2,936 lines

  1. /*******************  start of original comments  ********************/
  2. /*
  3.  * Written by Douglas Thomson (1989/1990)
  4.  *
  5.  * This source code is released into the public domain.
  6.  */
  7.  
  8. /*
  9.  * Name:    dte - Doug's Text Editor program - miscellaneous utilities
  10.  * Purpose: This file contains miscellaneous functions that were required
  11.  *           in more than one of the other files, or were thought to be
  12.  *           likely to be used elsewhere in the future.
  13.  * File:    utils.c
  14.  * Author:  Douglas Thomson
  15.  * System:  this file is intended to be system-independent
  16.  * Date:    October 1, 1989
  17.  */
  18. /*********************  end of original comments  ********************/
  19.  
  20.  
  21. /*
  22.  * The utility routines have been EXTENSIVELY rewritten.  Update screens as
  23.  * needed.  Most times, only one line has changed.  Just show changed line
  24.  * in all windows if it is on screen.
  25.  *
  26.  * Support routines for text lines longer than screen width have been added.
  27.  * Currently support lines as long as 1040 characters.
  28.  *
  29.  * In DTE, Doug chose to test whether characters are part of a word.  In TDE,
  30.  * we will test whether characters are not part of a word.  The character
  31.  * set not part of a word will not change as much as the characters that
  32.  * are part of a word.  In most languages, human and computer, the delimiters
  33.  * are much more common across languages than the tokens that make up a word.
  34.  * Thanks to Pierre Jelenc, pcj1@columbia.edu, for recommending looking for
  35.  * delimiters.
  36.  *
  37.  * New editor name:  TDE, the Thomson-Davis Editor.
  38.  * Author:           Frank Davis
  39.  * Date:             June 5, 1991, version 1.0
  40.  * Date:             July 29, 1991, version 1.1
  41.  * Date:             October 5, 1991, version 1.2
  42.  * Date:             January 20, 1992, version 1.3
  43.  * Date:             February 17, 1992, version 1.4
  44.  * Date:             April 1, 1992, version 1.5
  45.  * Date:             June 5, 1992, version 2.0
  46.  * Date:             October 31, 1992, version 2.1
  47.  * Date:             April 1, 1993, version 2.2
  48.  * Date:             June 5, 1993, version 3.0
  49.  * Date:             August 29, 1993, version 3.1
  50.  * Date:             November 13, 1993, version 3.2
  51.  *
  52.  * This modification of Douglas Thomson's code is released into the
  53.  * public domain, Frank Davis.  You may distribute it freely.
  54.  */
  55.  
  56. #include "tdestr.h"
  57. #include "common.h"
  58. #include "define.h"
  59. #include "tdefunc.h"
  60.  
  61.  
  62. /*
  63.  * Name:    myiswhitespc
  64.  * Purpose: To determine whether or not a character is *NOT* part of a "word".
  65.  * Date:    July 4, 1992
  66.  * Passed:  c: the character to be tested
  67.  * Returns: TRUE if c is in the character set *NOT* part of a word
  68.  * Notes:   The characters in the set not part of a word will not change as
  69.  *           as much as the characters that are part of a word.  In most
  70.  *           languages, human and computer, the delimiters are much more
  71.  *           common than the tokens that make up a word.  For example,
  72.  *           the set of punction characters don't change as much across
  73.  *           languages, human and computer, as the characters that make
  74.  *           up the alphabet, usually.  In other words, the delimiters
  75.  *           are fairly constant across languages.
  76.  */
  77. int  myiswhitespc( int c )
  78. {
  79.    return( c == ' ' || (bj_ispunct( c ) && c != '_') || bj_iscntrl( c ) );
  80. }
  81.  
  82.  
  83. /*
  84.  * Name:    check_virtual_col
  85.  * Purpose: ensure integrity of rcol, ccol, and bcol
  86.  * Date:    June 5, 1991
  87.  * Passed:  window:  pointer to current window
  88.  *          rcol: real column of cursor
  89.  *          ccol: current or logical column of cursor
  90.  */
  91. void check_virtual_col( TDE_WIN *window, int rcol, int ccol )
  92. {
  93. register int bcol;
  94. int  start_col;
  95. int  end_col;
  96. file_infos *file;
  97.  
  98.    file      = window->file_info;
  99.    bcol      = window->bcol;
  100.    start_col = window->start_col;
  101.    end_col   = window->end_col;
  102.  
  103.    /*
  104.     * is logical column past end of screen?
  105.     */
  106.    if (ccol > end_col) {
  107. /*      ccol = start_col + (end_col + 1 - start_col) / 2;  */
  108.       ccol = rcol - bcol + start_col;
  109.       if (ccol > end_col) {
  110.          ccol = end_col;
  111.          bcol = rcol - (ccol - start_col);
  112.          file->dirty = LOCAL;
  113. /*
  114.  *        ccol = start_col + (end_col + 1 - start_col) / 2;
  115.  *        bcol = rcol - ccol + start_col;
  116.  *        file->dirty = LOCAL;
  117.  */
  118.       }
  119.    }
  120.  
  121.    /*
  122.     * is logical column behind start of screen?
  123.     */
  124.    if (ccol < start_col) {
  125.       if (bcol >= (start_col - ccol))
  126.          bcol -= (start_col - ccol);
  127.       ccol = start_col;
  128.       file->dirty = LOCAL;
  129.    }
  130.  
  131.    /*
  132.     * is real column < base column?
  133.     */
  134.    if (rcol < bcol) {
  135.       ccol = rcol + start_col;
  136.       bcol = 0;
  137.       if (ccol > end_col) {
  138.          bcol = rcol;
  139.          ccol = start_col;
  140.       }
  141.       file->dirty = LOCAL;
  142.    }
  143.  
  144.    /*
  145.     * current column + base column MUST equal real column
  146.     */
  147.    if ((ccol - start_col) + bcol != rcol) {
  148.       if (bcol < 0 || bcol > rcol) {
  149.          bcol = rcol;
  150.          file->dirty = LOCAL;
  151.       }
  152.       ccol = rcol - bcol + start_col;
  153.       if (ccol > end_col) {
  154.          bcol = rcol;
  155.          ccol = start_col;
  156.          file->dirty = LOCAL;
  157.       }
  158.    }
  159.  
  160.    /*
  161.     * rcol CANNOT be negative
  162.     */
  163.    if (rcol < 0) {
  164.       rcol = bcol = 0;
  165.       ccol = start_col;
  166.       file->dirty = LOCAL;
  167.    }
  168.  
  169.    if (rcol >= MAX_LINE_LENGTH) {
  170.       rcol = MAX_LINE_LENGTH - 1;
  171.       bcol = rcol - (ccol - start_col);
  172.    }
  173.  
  174.    assert( rcol >= 0 );
  175.    assert( rcol < MAX_LINE_LENGTH );
  176.    assert( bcol >= 0 );
  177.    assert( bcol < MAX_LINE_LENGTH );
  178.    assert( ccol >= start_col );
  179.    assert( ccol <= end_col );
  180.  
  181.    window->bcol = bcol;
  182.    window->ccol = ccol;
  183.    window->rcol = rcol;
  184. }
  185.  
  186.  
  187. /*
  188.  * Name:    copy_line
  189.  * Purpose: To copy the cursor line, if necessary, into the current line
  190.  *           buffer, so that changes can be made efficiently.
  191.  * Date:    June 5, 1991
  192.  * Passed:  text_line: line to be copied to line buffer
  193.  *          line: line to display error message
  194.  * Notes:   See un_copy_line, the reverse operation.
  195.  *          DO NOT use the C library string functions on text in
  196.  *           g_status.line_buff, because Null characters are allowed as
  197.  *           normal text in the file.
  198.  */
  199. void copy_line( line_list_ptr ll )
  200. {
  201. register unsigned int len;
  202. text_ptr text_line;
  203.  
  204.    if (g_status.copied == FALSE  &&  ll->len != EOF) {
  205.  
  206.       assert( ll != NULL );
  207.  
  208.       len = ll->len;
  209.       text_line = ll->line;
  210.       g_status.buff_node = ll;
  211.  
  212.       assert( len < MAX_LINE_LENGTH );
  213.  
  214.       if (text_line != NULL)
  215.          my_memcpy( g_status.line_buff, text_line, len );
  216.  
  217.       g_status.line_buff_len = len;
  218.       g_status.copied = TRUE;
  219.    }
  220. }
  221.  
  222.  
  223. /*
  224.  * Name:    un_copy_line
  225.  * Purpose: To copy the cursor line, if necessary, from the current line
  226.  *           buffer, shifting the main text to make the right amount of
  227.  *           room.
  228.  * Date:    June 5, 1991
  229.  * Passed:  test_line:  location in file to copy line buffer
  230.  *          window:  pointer to current window
  231.  *          del_trailing:  delete the trailing blanks at eol? TRUE or FALSE
  232.  * Notes:   For some functions, trailing spaces should not be removed when
  233.  *           returning the line buffer to the main text.  The JoinLine function
  234.  *           is a good example.  We need to leave trailing space so when we
  235.  *           join lines - the current line will extend at least up to
  236.  *           the column of the cursor.  We need to leave trailing space
  237.  *           during BOX block operations.
  238.  *          See copy_line, the reverse operation.
  239.  */
  240. int  un_copy_line( line_list_ptr ll, TDE_WIN *window, int del_trailing )
  241. {
  242. text_ptr p;
  243. size_t len;     /* length of line buffer text */
  244. size_t ll_len;  /* length of ll->line */
  245. int  net_change;
  246. int  rc;
  247. char c;
  248. file_infos *file;
  249. TDE_WIN *wp;
  250.  
  251.    rc = OK;
  252.    if (mode.do_backups == TRUE)
  253.       rc = backup_file( window );
  254.  
  255.    if (g_status.copied == TRUE  &&  ll->len != EOF) {
  256.  
  257.       file = window->file_info;
  258.  
  259.       /*
  260.        * if we are deleting the entire line, don't worry about the
  261.        *  deleting the trailing space, since we're deleting entire line.
  262.        */
  263.       if (g_status.command == DeleteLine)
  264.          del_trailing = FALSE;
  265.  
  266.       if (del_trailing  &&  mode.trailing  &&  file->crlf != BINARY) {
  267.          len = g_status.line_buff_len;
  268.          for (p=(text_ptr)(g_status.line_buff+len); len > 0; len--, p--) {
  269.             c = *(p - 1);
  270.             if (c != ' '  &&  c != '\t')
  271.                break;
  272.             if (!mode.inflate_tabs && c == '\t')
  273.                break;
  274.          }
  275.          g_status.line_buff_len = len;
  276.          file->dirty = GLOBAL;
  277.          if (window->visible == TRUE)
  278.             show_changed_line( window );
  279.       }
  280.       len = g_status.line_buff_len;
  281.       ll_len =  (ll->line == NULL) ? 0 : ll->len;
  282.  
  283.  
  284.       assert( len < MAX_LINE_LENGTH );
  285.       assert( ll_len < MAX_LINE_LENGTH );
  286.  
  287.       net_change = len - ll_len;
  288.  
  289.       if (ll_len != len  ||  ll->line == NULL) {
  290.          /*
  291.           * let malloc space for the new line before we free the old line.
  292.           */
  293.          p = my_malloc( len, &rc );
  294.          if (rc == ERROR)
  295.             error( WARNING, window->bottom_line, main4 );
  296.  
  297.          /*
  298.           * free the space taken up by current line in FAR heap.
  299.           */
  300.          if (rc != ERROR  &&  ll->line != NULL)
  301.             my_free( ll->line );
  302.       } else
  303.          p = ll->line;
  304.  
  305.       if (rc != ERROR) {
  306.          if (len > 0)
  307.             my_memcpy( p, g_status.line_buff, len );
  308.          ll->line = p;
  309.          ll->len = len;
  310.  
  311.          if (net_change != 0) {
  312.             for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  313.                if (wp->file_info == file && wp != window)
  314.                   if (wp->rline > window->rline)
  315.                      wp->bin_offset += net_change;
  316.             }
  317.          }
  318.  
  319.          file->modified = TRUE;
  320.          show_avail_mem( );
  321.       }
  322.    }
  323.    g_status.copied = FALSE;
  324.    return( rc );
  325. }
  326.  
  327.  
  328. /*
  329.  * Name:    un_copy_tab_buffer
  330.  * Purpose: To copy the tab buffer line the main text buffer
  331.  * Date:    October 31, 1992
  332.  * Passed:  line_number:  line number to copy line tab out buffer
  333.  *          window:       pointer to current window
  334.  */
  335. int  un_copy_tab_buffer( line_list_ptr ll, TDE_WIN *window )
  336. {
  337. text_ptr p;
  338. int  len;               /* length of current line buffer text */
  339. int  net_change;
  340. int  rc;
  341. file_infos *file;
  342. TDE_WIN *wp;
  343.  
  344.    rc = OK;
  345.    file = window->file_info;
  346.    /*
  347.     * file has changed.  lets create the back_up if needed
  348.     */
  349.    if (mode.do_backups == TRUE) {
  350.       window->file_info->modified = TRUE;
  351.       rc = backup_file( window );
  352.    }
  353.  
  354.    len = g_status.tabout_buff_len;
  355.  
  356.    assert( len >= 0 );
  357.    assert( len < MAX_LINE_LENGTH );
  358.    assert( ll->len >= 0 );
  359.    assert( ll->len < MAX_LINE_LENGTH );
  360.  
  361.    /*
  362.     * if the FAR heap has run out of space, then only part of the
  363.     *  current line can be moved back into the FAR heap. Warn the user
  364.     *  that some of the current line has been lost.
  365.     */
  366.    p = my_malloc( len, &rc );
  367.    if (rc == ERROR)
  368.       error( WARNING, window->bottom_line, main4 );
  369.  
  370.    if (rc == OK) {
  371.       net_change = len - ll->len;
  372.  
  373.       if (ll->line != NULL)
  374.          my_free( ll->line );
  375.       if (len > 0)
  376.          my_memcpy( p, g_status.line_buff, len );
  377.       ll->line = p;
  378.       ll->len  = len;
  379.  
  380.       if (net_change != 0) {
  381.          for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  382.             if (wp->file_info == file && wp != window)
  383.                if (wp->rline > window->rline)
  384.                   wp->bin_offset += net_change;
  385.          }
  386.       }
  387.  
  388.       file->modified = TRUE;
  389.    }
  390.    return( rc );
  391. }
  392.  
  393.  
  394. /*
  395.  * Name:    load_undo_buffer
  396.  * Purpose: To copy the cursor line to the undo buffer.
  397.  * Date:    September 26, 1991
  398.  * Passed:  file:          pointer to file
  399.  *          line_to_undo:  pointer to line in file to save
  400.  * Notes:   save the last mode.undo_max lines in a stack.  when we overflow
  401.  *           the stack, dump the oldest line.
  402.  */
  403. void load_undo_buffer( file_infos *file, text_ptr line_to_undo, int len )
  404. {
  405. int  rc;
  406. text_ptr l;
  407. line_list_ptr temp_ll;
  408.  
  409.    rc = OK;
  410.    if (file->undo_count >= mode.undo_max) {
  411.       --file->undo_count;
  412.       temp_ll = file->undo_bot->prev;
  413.       temp_ll->prev->next = file->undo_bot;
  414.       file->undo_bot->prev = temp_ll->prev;
  415.       if (temp_ll->line != NULL)
  416.          my_free( temp_ll->line );
  417.    } else
  418.       temp_ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
  419.  
  420.    assert( len >= 0 );
  421.    assert( len < MAX_LINE_LENGTH );
  422.  
  423.    l = my_malloc( len, &rc );
  424.  
  425.    if (rc == ERROR) {
  426.       if (l != NULL)
  427.          my_free( l );
  428.       if (temp_ll != NULL)
  429.          my_free( temp_ll );
  430.    } else {
  431.       if (len > 0)
  432.          my_memcpy( l, line_to_undo, len );
  433.       temp_ll->line  = l;
  434.       temp_ll->len   = len;
  435.       temp_ll->dirty = TRUE;
  436.  
  437.       temp_ll->prev = NULL;
  438.       temp_ll->next = file->undo_top;
  439.       file->undo_top->prev = temp_ll;
  440.       file->undo_top = temp_ll;
  441.  
  442.       ++file->undo_count;
  443.    }
  444. }
  445.  
  446.  
  447. /*
  448.  * Name:    set_prompt
  449.  * Purpose: To display a prompt, highlighted, at the bottom of the screen.
  450.  * Date:    October 1, 1989
  451.  * Passed:  prompt: prompt to be displayed
  452.  *          line:   line to display prompt
  453.  */
  454. void set_prompt( char *prompt, int line )
  455. {
  456. register int prompt_col;
  457.  
  458.    /*
  459.     * work out where the answer should go
  460.     */
  461.    prompt_col = strlen( prompt );
  462.  
  463.    assert( prompt_col <= g_display.ncols );
  464.  
  465.    /*
  466.     * output the prompt
  467.     */
  468.    s_output( prompt, line, 0, g_display.message_color );
  469.    eol_clear( prompt_col, line, g_display.message_color );
  470.  
  471.    /*
  472.     * put cursor at end of prompt
  473.     */
  474.    xygoto( prompt_col, line );
  475. }
  476.  
  477.  
  478. /*
  479.  * Name:    get_name
  480.  * Purpose: To prompt the user and read the string entered in response.
  481.  * Date:    June 5, 1992
  482.  * Passed:  prompt: prompt to offer the user
  483.  *          line:   line to display prompt
  484.  *          name:   default answer
  485.  *          color:  color to display prompt
  486.  * Returns: name:   user's answer
  487.  *          OK if user entered something
  488.  *          ERROR if user aborted the command
  489.  * Notes:   with the addition of macros in tde, this function became a little
  490.  *           more complicated.  we have to deal with both executing macros
  491.  *           and macros that are the user uses when entering normal text
  492.  *           at the prompt.  i call these local and global macros.  a global
  493.  *           macro is when this function is called from a running macro.
  494.  *           the running macro can enter text and return from this function
  495.  *           w/o any action from the user.  a local macro is when the user
  496.  *           presses a key inside this function, which happens quite often
  497.  *           when keys are assigned to ASCII and Extended ASCII characters.
  498.  */
  499. int  get_name( char *prompt, int line, char *name, int color )
  500. {
  501. int  col;               /* cursor column for answer */
  502. int  c;                 /* character user just typed */
  503. char *cp;               /* cursor position in answer */
  504. char *answer;           /* user's answer */
  505. int first = TRUE;       /* first character typed */
  506. register int len;       /* length of answer */
  507. int  plen;              /* length of prompt */
  508. int  func;              /* function of key pressed */
  509. int  stop;              /* flag to stop getting characters */
  510. char *p;                /* for copying text in answer */
  511. char buffer[MAX_COLS+2];/* line on which name is being entered */
  512. int  normal;
  513. int  local_macro = FALSE;
  514. int  next;
  515. int  regx_help_on;
  516. char **pp;
  517. int  i;
  518. #if defined( __UNIX__ )
  519.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  520. #else
  521.  char display_buff[(MAX_COLS+2)*2];
  522. #endif
  523.  
  524.    /*
  525.     * set up prompt and default
  526.     */
  527.    assert( strlen( prompt ) < (size_t)g_display.ncols );
  528.    assert( strlen( name )   < (size_t)g_display.ncols );
  529.  
  530.    strcpy( buffer, prompt );
  531.    plen = strlen( prompt );
  532.    answer = buffer + plen;
  533.    strcpy( answer, name );
  534.  
  535.    /*
  536.     * let user edit default string
  537.     */
  538.    next = regx_help_on = FALSE;
  539.    len = strlen( answer );
  540.    col = strlen( buffer );
  541.    g_status.prompt_line = line;
  542.    g_status.prompt_col = col;
  543.    cp = answer + len;
  544.    normal = g_display.text_color;
  545.    save_screen_line( 0, line, display_buff );
  546.    s_output( buffer, line, 0, color );
  547.    eol_clear( col, line, normal );
  548.    for (stop = FALSE; stop == FALSE;) {
  549.       if (regx_help_on == TRUE)
  550.          xygoto( -1, -1 );
  551.       else
  552.          xygoto( col, line );
  553.       if (g_status.macro_executing) {
  554.          next = g_status.macro_next;
  555.          g_status.macro_next = macro.strokes[g_status.macro_next].next;
  556.          if (g_status.macro_next != -1) {
  557.             c = macro.strokes[g_status.macro_next].key;
  558.             func = getfunc( c );
  559.             if (func == PlayBack) {
  560.                stop = TRUE;
  561.                g_status.macro_next = next;
  562.             }
  563.          } else {
  564.             c = 0x100;
  565.             func = AbortCommand;
  566.             stop = TRUE;
  567.          }
  568.       } else {
  569.          if (local_macro == FALSE) {
  570.             c = getkey( );
  571.             func = getfunc( c );
  572.  
  573.             /*
  574.              * User may have redefined the Enter and ESC keys.  Make the Enter
  575.              *  key perform a Rturn in this function. Make the ESC key do an
  576.              *  AbortCommand.
  577.              */
  578.             if (c == RTURN)
  579.                func = Rturn;
  580.             else if (c == ESC)
  581.                func = AbortCommand;
  582.  
  583.             if (func == PlayBack) {
  584.                local_macro = TRUE;
  585.                next = macro.first_stroke[ c-256 ];
  586.                c = macro.strokes[next].key;
  587.                func = getfunc( c );
  588.                next = macro.strokes[next].next;
  589.             } else {
  590.                g_status.key_pressed = c;
  591.                record_keys( line );
  592.             }
  593.          } else {
  594.             if (next != -1) {
  595.                c = macro.strokes[next].key;
  596.                next = macro.strokes[next].next;
  597.             } else {
  598.                local_macro = FALSE;
  599.                c = 0x100;
  600.             }
  601.             func = getfunc( c );
  602.          }
  603.       }
  604.       if (c == _F1)
  605.          func = Help;
  606.       if (regx_help_on == TRUE  &&  g_status.current_window != NULL) {
  607.          redraw_screen( g_status.current_window );
  608.          s_output( buffer, line, 0, color );
  609.          eol_clear( col, line, normal );
  610.          s_output( cp, line, col, color );
  611.          regx_help_on = FALSE;
  612.       } else {
  613.          switch (func) {
  614.             case Help :
  615.                if ((g_status.command == FindRegX  ||
  616.                     g_status.command == RepeatFindRegX) &&
  617.                     regx_help_on == FALSE) {
  618.                   regx_help_on = TRUE;
  619.                   for (i=3,pp=regx_help; *pp != NULL; pp++, i++)
  620.                      s_output( *pp, i, 12, g_display.help_color );
  621.                }
  622.                break;
  623.             case ToggleSearchCase :
  624.                mode.search_case = mode.search_case == IGNORE ? MATCH : IGNORE;
  625.                build_boyer_array( );
  626.                show_search_case( );
  627.                break;
  628.             case Rturn       :
  629.             case NextLine    :
  630.             case BegNextLine :
  631.                answer[len] = '\0';
  632.                assert( strlen( answer ) < (size_t)g_display.ncols );
  633.                strcpy( name, answer );
  634.                /*
  635.                 * finished
  636.                 */
  637.                stop = TRUE;
  638.                break;
  639.             case BackSpace :
  640.                /*
  641.                 * delete to left of cursor
  642.                 */
  643.                if (cp > answer) {
  644.                   for (p=cp-1; p < answer+len; p++) {
  645.                      *p = *(p+1);
  646.                   }
  647.                   --len;
  648.                   --col;
  649.                   --cp;
  650.                   c_output( ' ', plen+len, line, normal );
  651.                   s_output( cp, line, col, color );
  652.                   *(answer + len) = '\0';
  653.                }
  654.                break;
  655.             case DeleteChar :
  656.                /*
  657.                 * delete char under cursor
  658.                 */
  659.                if (*cp) {
  660.                   for (p=cp; p < answer+len; p++) {
  661.                      *p = *(p+1);
  662.                   }
  663.                   --len;
  664.                   c_output( ' ', plen+len, line, normal );
  665.                   s_output( cp, line, col, color );
  666.                   *(answer + len) = '\0';
  667.                }
  668.                break;
  669.             case DeleteLine :
  670.                /*
  671.                 * delete current line
  672.                 */
  673.                col = plen;
  674.                cp = answer;
  675.                *cp = '\0';
  676.                len = 0;
  677.                eol_clear( col, line, normal );
  678.                break;
  679.             case AbortCommand :
  680.                stop = TRUE;
  681.                break;
  682.             case CharLeft :
  683.                /*
  684.                 * move cursor left
  685.                 */
  686.                if (cp > answer) {
  687.                   col--;
  688.                   cp--;
  689.                }
  690.                break;
  691.             case CharRight :
  692.                /*
  693.                 * move cursor right
  694.                 */
  695.                if (*cp) {
  696.                   col++;
  697.                   cp++;
  698.                 }
  699.                 break;
  700.             case BegOfLine :
  701.                /*
  702.                 * move cursor to start of line
  703.                 */
  704.                col = plen;
  705.                cp = answer;
  706.                break;
  707.             case EndOfLine :
  708.                /*
  709.                 * move cursor to end of line
  710.                 */
  711.                col = plen + len;
  712.                cp = answer + len;
  713.                break;
  714.             default :
  715.                if (c < 0x100) {
  716.                   /*
  717.                    * insert character at cursor
  718.                    */
  719.                   if (first) {
  720.                      /*
  721.                       * delete previous answer
  722.                       */
  723.                      col = plen;
  724.                      cp = answer;
  725.                      *cp = '\0';
  726.                      len = 0;
  727.                      eol_clear( col, line, normal );
  728.                   }
  729.  
  730.                   /*
  731.                    * insert new character
  732.                    */
  733.                   if (col < g_display.ncols-1) {
  734.                      if (*cp == '\0') {
  735.                         ++len;
  736.                         *(answer + len) = '\0';
  737.                      }
  738.                      *cp = (char)c;
  739.                      c_output( c, col, line, color );
  740.                      ++cp;
  741.                      ++col;
  742.                   }
  743.                }
  744.                break;
  745.          }
  746.       }
  747.       first = FALSE;
  748.    }
  749.    restore_screen_line( 0, line, display_buff );
  750.    return( func == AbortCommand ? ERROR : OK );
  751. }
  752.  
  753.  
  754. /*
  755.  * Name:     get_sort_order
  756.  * Purpose:  To prompt the user and get sort direction
  757.  * Date:     June 5, 1992
  758.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  759.  * Passed:   window
  760.  * Returns:  OK if user entered something
  761.  *           ERROR if user aborted the command
  762.  */
  763. int  get_sort_order( TDE_WIN *window )
  764. {
  765. register int c;
  766. int  col;
  767. #if defined( __UNIX__ )
  768.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  769. #else
  770.  char display_buff[(MAX_COLS+2)*2];
  771. #endif
  772.  
  773.    save_screen_line( 0, window->bottom_line, display_buff );
  774.    /*
  775.     * sort ascending or descending
  776.     */
  777.    s_output( utils4, window->bottom_line, 0, g_display.message_color );
  778.    c = strlen( utils4 );
  779.    eol_clear( c, window->bottom_line, g_display.text_color );
  780.    xygoto( c, window->bottom_line );
  781.    do {
  782.       c = getanswerkey( );
  783.       col = getfunc( c );
  784.       if (c == ESC)
  785.          col = AbortCommand;
  786.    } while (col != AbortCommand  &&  c != L_ASCENDING  &&  c != L_DESCENDING);
  787.    switch ( c ) {
  788.       case L_ASCENDING :
  789.          sort.direction = ASCENDING;
  790.          break;
  791.       case L_DESCENDING :
  792.          sort.direction = DESCENDING;
  793.          break;
  794.       default  :
  795.          col = AbortCommand;
  796.          break;
  797.    }
  798.    restore_screen_line( 0, window->bottom_line, display_buff );
  799.    return( col == AbortCommand ? ERROR : OK );
  800. }
  801.  
  802.  
  803. /*
  804.  * Name:     get_replace_direction
  805.  * Purpose:  To prompt the user and get replace string direction
  806.  * Date:     October 31, 1992
  807.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  808.  * Passed:   window
  809.  * Returns:  OK if user entered something
  810.  *           ERROR if user aborted the command
  811.  */
  812. int  get_replace_direction( TDE_WIN *window )
  813. {
  814. register int c;
  815. int  col;
  816. #if defined( __UNIX__ )
  817.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  818. #else
  819.  char display_buff[(MAX_COLS+2)*2];
  820. #endif
  821.  
  822.    save_screen_line( 0, window->bottom_line, display_buff );
  823.    /*
  824.     * replace forward or backward
  825.     */
  826.    s_output( utils5, window->bottom_line, 0, g_display.message_color );
  827.    c = strlen( utils5 );
  828.    eol_clear( c, window->bottom_line, g_display.text_color );
  829.    xygoto( c, window->bottom_line );
  830.    do {
  831.       c = getanswerkey( );
  832.       col = getfunc( c );
  833.       if (c == ESC)
  834.          col = AbortCommand;
  835.    } while (col != AbortCommand  &&  c != L_FORWARD  &&  c != L_BACKWARD);
  836.    switch ( c ) {
  837.       case L_FORWARD :
  838.          c = FORWARD;
  839.          break;
  840.       case L_BACKWARD :
  841.          c = BACKWARD;
  842.          break;
  843.       default  :
  844.          c = ERROR;
  845.    }
  846.    restore_screen_line( 0, window->bottom_line, display_buff );
  847.    return( col == AbortCommand ? ERROR : c );
  848. }
  849.  
  850.  
  851. /*
  852.  * Name:     get_yn
  853.  * Purpose:  To input a response of yes or no.
  854.  * Date:     October 1, 1989
  855.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  856.  * Returns:  the user's answer.  A_??? - see tdestr.h
  857.  */
  858. int  get_yn( void )
  859. {
  860. int  c;                 /* the user's response */
  861. register int rc;        /* return code */
  862.  
  863.    do {
  864.       c = getanswerkey( );
  865.       rc = getfunc( c );
  866.       if (c== ESC)
  867.          rc = AbortCommand;
  868.    } while (rc != AbortCommand  &&  c != L_YES  &&  c != L_NO);
  869.    if (rc == AbortCommand || c == ESC)
  870.       rc = ERROR;
  871.    else {
  872.       switch ( c ) {
  873.          case L_YES :
  874.             rc = A_YES;
  875.             break;
  876.          case L_NO :
  877.             rc = A_NO;
  878.             break;
  879.       }
  880.    }
  881.    return( rc );
  882. }
  883.  
  884.  
  885. /*
  886.  * Name:     get_lr
  887.  * Purpose:  To input a response of yes or no.
  888.  * Date:     June 1, 1991
  889.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  890.  * Returns:  the user's answer, LEFT or RIGHT.
  891.  */
  892. int  get_lr( void )
  893. {
  894. int  c;                 /* the user's response */
  895. register int rc;        /* return code */
  896.  
  897.    for (rc=OK; rc == OK;) {
  898.       c = getanswerkey( );
  899.       if (getfunc( c ) == AbortCommand || c == ESC)
  900.          rc = ERROR;
  901.       else {
  902.          switch ( c ) {
  903.             case L_LEFT :
  904.                rc = LEFT;
  905.                break;
  906.             case L_RIGHT :
  907.                rc = RIGHT;
  908.                break;
  909.          }
  910.       }
  911.    }
  912.    return( rc );
  913. }
  914.  
  915.  
  916. /*
  917.  * Name:     get_bc
  918.  * Purpose:  To input a response of beginning or current cursor postion
  919.  * Date:     October 31, 1992
  920.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  921.  * Returns:  the user's answer, Beginning or Current.
  922.  */
  923. int  get_bc( void )
  924. {
  925. int  c;                 /* the user's response */
  926. register int rc;        /* return code */
  927.  
  928.    for (rc=OK; rc == OK;) {
  929.       c = getanswerkey( );
  930.       if (getfunc( c ) == AbortCommand || c == ESC)
  931.          rc = ERROR;
  932.       else {
  933.          switch ( c ) {
  934.             case L_BEGINNING :
  935.                rc = BEGINNING;
  936.                break;
  937.             case L_CURRENT :
  938.             case 'c' :
  939.                rc = CURRENT;
  940.                break;
  941.          }
  942.       }
  943.    }
  944.    return( rc );
  945. }
  946.  
  947.  
  948. /*
  949.  * Name:     get_oa
  950.  * Purpose:  To input a response of overwrite or append.
  951.  * Date:     October 1, 1989
  952.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  953.  * Returns:  the user's answer.  A_??? - see tdestr.h
  954.  */
  955. int  get_oa( void )
  956. {
  957. int  c;                 /* the user's response */
  958. register int rc;        /* return code */
  959. int  func;
  960.  
  961.    rc = 0;
  962.    while (rc != AbortCommand && rc != A_OVERWRITE && rc != A_APPEND) {
  963.       c = getanswerkey( );
  964.       func = getfunc( c );
  965.       if (func == AbortCommand || c == ESC)
  966.          rc = AbortCommand;
  967.       switch ( c ) {
  968.          case L_OVERWRITE :
  969.             rc = A_OVERWRITE;
  970.             break;
  971.          case L_APPEND :
  972.             rc = A_APPEND;
  973.             break;
  974.       }
  975.    }
  976.    return( rc );
  977. }
  978.  
  979.  
  980. /*
  981.  * Name:    show_eof
  982.  * Purpose: display eof message
  983.  * Date:    September 16, 1991
  984.  * Notes:   line:  ususally, line to is display "<=== eof ===>"
  985.  */
  986. void show_eof( TDE_WIN *window )
  987. {
  988. register int color;
  989. char temp[MAX_COLS+2];
  990.  
  991.    assert( strlen( mode.eof ) < (size_t)g_display.ncols );
  992.  
  993.    strcpy( temp, mode.eof );
  994.    color = window->end_col + 1 - window->start_col;
  995.    if (strlen( temp ) > (unsigned)color)
  996.       temp[color] = '\0';
  997.    color = g_display.eof_color;
  998.    window_eol_clear( window, color );
  999.    s_output( temp, window->cline, window->start_col, color );
  1000. }
  1001.  
  1002.  
  1003. /*
  1004.  * Name:    display_current_window
  1005.  * Purpose: display text in current window
  1006.  * Date:    June 5, 1991
  1007.  * Passed:  window:  pointer to current window
  1008.  * Notes:   use a temporary window structure, "w", to do the dirty work.
  1009.  */
  1010. void display_current_window( TDE_WIN *window )
  1011. {
  1012. int  count;     /* number of lines updated so far */
  1013. int  number;    /* number of lines visible in window */
  1014. register int i; /* register variable */
  1015. TDE_WIN w;      /* scratch window structure */
  1016. int  curl;      /* current line on screen, window->cline */
  1017. int  eof;
  1018.  
  1019.    /*
  1020.     * initialize the scratch variables
  1021.     */
  1022.    number = window->bottom_line - ((window->top_line + window->ruler) - 1);
  1023.    count  = window->cline - (window->top_line + window->ruler);
  1024.    dup_window_info( &w, window );
  1025.  
  1026.    w.cline -= count;
  1027.    w.rline -= count;
  1028.    for (eof=count; eof > 0; eof--)
  1029.       w.ll = w.ll->prev;
  1030.  
  1031.  
  1032.    /*
  1033.     * start at the top of the window and display a window full of text
  1034.     */
  1035.    eof = FALSE;
  1036.    curl = window->cline;
  1037.    for (i=number; i>0; i--) {
  1038.       if (w.ll->len != EOF) {
  1039.          /*
  1040.           * if this is window->cline, do not show the line because we
  1041.           *  show the curl at the end of this function.  don't show it twice
  1042.           */
  1043.          if (w.cline != curl)
  1044.             update_line( &w );
  1045.          w.ll = w.ll->next;
  1046.       } else if (eof == FALSE) {
  1047.          show_eof( &w );
  1048.          eof = TRUE;
  1049.       } else
  1050.          window_eol_clear( &w, COLOR_TEXT );
  1051.       ++w.cline;
  1052.       ++w.rline;
  1053.    }
  1054.    show_asterisk( window );
  1055.    show_curl_line( window );
  1056. }
  1057.  
  1058.  
  1059. /*
  1060.  * Name:    redraw_screen
  1061.  * Purpose: display all visible windows, modes, and headers
  1062.  * Date:    June 5, 1991
  1063.  * Passed:  window:  pointer to current window
  1064.  */
  1065. int  redraw_screen( TDE_WIN *window )
  1066. {
  1067. register TDE_WIN *above;        /* window above current */
  1068. register TDE_WIN *below;        /* window below current */
  1069.  
  1070. #if defined( __UNIX__ )
  1071.    touchwin( curscr );
  1072. #endif
  1073.  
  1074.    cls( );
  1075.  
  1076.    /*
  1077.     * display the current window
  1078.     */
  1079.    redraw_current_window( window );
  1080.  
  1081.    /*
  1082.     * now update all the other windows
  1083.     */
  1084.    above = below = window;
  1085.    while (above->prev || below->next) {
  1086.       if (above->prev) {
  1087.          above = above->prev;
  1088.          redraw_current_window( above );
  1089.       }
  1090.       if (below->next) {
  1091.          below = below->next;
  1092.          redraw_current_window( below );
  1093.       }
  1094.    }
  1095.    window->file_info->dirty = FALSE;
  1096.    show_modes( );
  1097.  
  1098. #if defined( __UNIX__ )
  1099.    refresh( );
  1100. #endif
  1101.  
  1102.    return( OK );
  1103. }
  1104.  
  1105.  
  1106. /*
  1107.  * Name:    redraw_current_window
  1108.  * Purpose: redraw all info in window
  1109.  * Date:    July 13, 1991
  1110.  * Passed:  window:  pointer to current window
  1111.  */
  1112. void redraw_current_window( TDE_WIN *window )
  1113. {
  1114.  
  1115.    /*
  1116.     * display the current window
  1117.     */
  1118.    if (window->visible) {
  1119.       display_current_window( window );
  1120.       show_window_header( window );
  1121.       show_ruler( window );
  1122.       show_ruler_pointer( window );
  1123.       if (window->vertical)
  1124.          show_vertical_separator( window );
  1125.    }
  1126. }
  1127.  
  1128.  
  1129. /*
  1130.  * Name:    show_changed_line
  1131.  * Purpose: Only one line was changed in file, just show it
  1132.  * Date:    June 5, 1991
  1133.  * Passed:  window:  pointer to current window
  1134.  */
  1135. void show_changed_line( TDE_WIN *window )
  1136. {
  1137. TDE_WIN *above;                 /* window above current */
  1138. TDE_WIN *below;                 /* window below current */
  1139. TDE_WIN w;                      /* scratch window structure */
  1140. long changed_line;              /* line number in file that was changed */
  1141. long top_line, bottom_line;     /* top and bottom line in file on screen */
  1142. int  line_on_screen;            /* is changed line on screen? */
  1143. file_infos *file;               /* file pointer */
  1144.  
  1145.    file = window->file_info;
  1146.    if ((file->dirty == LOCAL || file->dirty == GLOBAL) && window->visible)
  1147.       show_curl_line( window );
  1148.    changed_line = window->rline;
  1149.  
  1150.    /*
  1151.     * now update the line in all other windows
  1152.     */
  1153.    if (file->dirty != LOCAL) {
  1154.       above = below = window;
  1155.       while (above->prev || below->next) {
  1156.          if (above->prev) {
  1157.             above = above->prev;
  1158.             dup_window_info( &w, above );
  1159.          } else if (below->next) {
  1160.             below = below->next;
  1161.             dup_window_info( &w, below );
  1162.          }
  1163.  
  1164.          /*
  1165.           * is this window the changed file and is it visible?
  1166.           */
  1167.          if (w.file_info == file && w.visible) {
  1168.  
  1169.             /*
  1170.              * calculate file lines at top and bottom of screen.
  1171.              * the changed line may not be the curl in other windows.
  1172.              */
  1173.             line_on_screen = FALSE;
  1174.             top_line = w.rline - (w.cline - (w.top_line + w.ruler));
  1175.             bottom_line = w.rline + (w.bottom_line - w.cline);
  1176.             if (changed_line == w.rline)
  1177.                line_on_screen = CURLINE;
  1178.             else if (changed_line < w.rline && changed_line >= top_line) {
  1179.                line_on_screen = NOTCURLINE;
  1180.                while (w.rline > changed_line) {
  1181.                   w.ll = w.ll->prev;
  1182.                   --w.rline;
  1183.                   --w.cline;
  1184.                }
  1185.             } else if (changed_line > w.rline && changed_line <= bottom_line) {
  1186.                line_on_screen = NOTCURLINE;
  1187.                while (w.rline < changed_line) {
  1188.                   w.ll = w.ll->next;
  1189.                   ++w.rline;
  1190.                   ++w.cline;
  1191.                }
  1192.             }
  1193.  
  1194.             /*
  1195.              * display the changed line if on screen
  1196.              */
  1197.             if (line_on_screen == NOTCURLINE)
  1198.                update_line( &w );
  1199.             else if (line_on_screen == CURLINE)
  1200.                show_curl_line( &w );
  1201.          }
  1202.       }
  1203.    }
  1204.    file->dirty = FALSE;
  1205. }
  1206.  
  1207.  
  1208. /*
  1209.  * Name:    show_curl_line
  1210.  * Purpose: show current line in curl color
  1211.  * Date:    January 16, 1992
  1212.  * Passed:  window:  pointer to current window
  1213.  */
  1214. void show_curl_line( TDE_WIN *window )
  1215. {
  1216. int  text_color;
  1217. int  dirty_color;
  1218.  
  1219.    if (window->visible  &&  g_status.screen_display) {
  1220.       text_color = g_display.text_color;
  1221.       dirty_color = g_display.dirty_color;
  1222.       g_display.dirty_color = g_display.text_color = g_display.curl_color;
  1223.       update_line( window );
  1224.       g_display.text_color = text_color;
  1225.       g_display.dirty_color = dirty_color;
  1226.    }
  1227. }
  1228.  
  1229.  
  1230. /*
  1231.  * Name:    dup_window_info
  1232.  * Purpose: Copy window info from one window pointer to another
  1233.  * Date:    June 5, 1991
  1234.  * Passed:  dw: destination window
  1235.  *          sw: source window
  1236.  */
  1237. void dup_window_info( TDE_WIN *dw, TDE_WIN *sw )
  1238. {
  1239.    memcpy( dw, sw, sizeof( TDE_WIN ) );
  1240. }
  1241.  
  1242.  
  1243. /*
  1244.  * Name:    adjust_windows_cursor
  1245.  * Purpose: A change has been made, make sure pointers are not ahead of
  1246.  *           or behind file.
  1247.  * Date:    June 5, 1991
  1248.  * Passed:  window:       pointer to current window
  1249.  *          line_change:  number of lines add to or subtracted from file
  1250.  * Notes:   If a file has been truncated in one window and there is another
  1251.  *           window open to the same file and its current line is near the
  1252.  *           end, the current line is reset to the last line of the file.
  1253.  */
  1254. void adjust_windows_cursor( TDE_WIN *window, long line_change )
  1255. {
  1256. register TDE_WIN *next;
  1257. long i;
  1258. file_infos *file;
  1259. MARKER *marker;
  1260. long length;
  1261.  
  1262.    file = window->file_info;
  1263.    length = file->length;
  1264.    next = g_status.window_list;
  1265.    while (next != NULL) {
  1266.       if (next != window) {
  1267.          if (next->file_info == file) {
  1268.             if (next->rline > length + 1) {
  1269.                next->rline = length;
  1270.                next->ll    = file->line_list_end;
  1271.                file->dirty = NOT_LOCAL;
  1272.             } else if (next->rline < 1) {
  1273.                next->rline = 1;
  1274.                next->cline = next->top_line + next->ruler;
  1275.                next->ll    = file->line_list;
  1276.                next->bin_offset = 0;
  1277.                file->dirty = NOT_LOCAL;
  1278.             }
  1279.             if (next->rline > window->rline  &&  line_change) {
  1280.                file->dirty = NOT_LOCAL;
  1281.                if (line_change < 0) {
  1282.                   for (i=line_change; i < 0 && next->ll->next != NULL; i++) {
  1283.                      next->bin_offset += next->ll->len;
  1284.                      next->ll = next->ll->next;
  1285.                   }
  1286.                } else if (line_change > 0) {
  1287.                   for (i=line_change; i > 0 && next->ll->prev != NULL; i--) {
  1288.                      next->ll = next->ll->prev;
  1289.                      next->bin_offset -= next->ll->len;
  1290.                   }
  1291.                }
  1292.             }
  1293.             if (next->rline < (next->cline -(next->top_line+next->ruler-1))) {
  1294.                next->cline = (int)next->rline+(next->top_line+next->ruler)-1;
  1295.                file->dirty = NOT_LOCAL;
  1296.             }
  1297.          }
  1298.       }
  1299.       next = next->next;
  1300.    }
  1301.  
  1302.    /*
  1303.     * now adjust any markers.
  1304.     */
  1305.    for (i=0; i<3; i++) {
  1306.       marker = &file->marker[ (int) i ];
  1307.       if (marker->rline > window->rline) {
  1308.          marker->rline += line_change;
  1309.          if (marker->rline < 1L)
  1310.             marker->rline = 1L;
  1311.          else if (marker->rline > length)
  1312.             marker->rline = length;
  1313.       }
  1314.    }
  1315. }
  1316.  
  1317.  
  1318. /*
  1319.  * Name:    first_non_blank
  1320.  * Purpose: To find the column of the first non-blank character
  1321.  * Date:    June 5, 1991
  1322.  * Passed:  s:    the string to search
  1323.  *          len:  length of string
  1324.  * Returns: the first non-blank column
  1325.  */
  1326. int  first_non_blank( text_ptr s, int len )
  1327. {
  1328. register int count = 0;
  1329.  
  1330.    if (s != NULL) {
  1331.       if (mode.inflate_tabs) {
  1332.          for (; len > 0 && (*s == ' ' || *s == '\t'); s++, len--) {
  1333.             if (*s != '\t')
  1334.                ++count;
  1335.             else
  1336.                count += mode.ptab_size - (count % mode.ptab_size);
  1337.          }
  1338.       } else {
  1339.          while (len-- > 0  &&  *s++ == ' ')
  1340.            ++count;
  1341.       }
  1342.    }
  1343.    return( count );
  1344. }
  1345.  
  1346.  
  1347. /*
  1348.  * Name:    find_end
  1349.  * Purpose: To find the last character in a line
  1350.  * Date:    October 31, 1992
  1351.  * Passed:  s:    the string to search
  1352.  *          len:  length of string
  1353.  * Returns: the first non-blank column
  1354.  */
  1355. int  find_end( text_ptr s, int len )
  1356. {
  1357. register int count = 0;
  1358.  
  1359.    if (s != NULL) {
  1360.       if (mode.inflate_tabs) {
  1361.          for (;len > 0; s++, len--) {
  1362.             if (*s == '\t')
  1363.                count += mode.ptab_size - (count % mode.ptab_size);
  1364.             else
  1365.                ++count;
  1366.          }
  1367.       } else
  1368.          count = len;
  1369.    }
  1370.    return( count );
  1371. }
  1372.  
  1373.  
  1374. /*
  1375.  * Name:    is_line_blank
  1376.  * Purpose: is line empty or does it only contain spaces?
  1377.  * Date:    November 28, 1991
  1378.  * Passed:  s:    the string to search
  1379.  *          len:  length of string
  1380.  * Returns: TRUE if line is blank or FALSE if something is in line
  1381.  */
  1382. int is_line_blank( text_ptr s, int len )
  1383. {
  1384.    if (s != NULL) {
  1385.       if (mode.inflate_tabs) {
  1386.         while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  1387.            ++s;
  1388.            --len;
  1389.         }
  1390.       } else {
  1391.          while (len > 0  &&  *s == ' ') {
  1392.             ++s;
  1393.             --len;
  1394.          }
  1395.       }
  1396.    } else
  1397.       len = 0;
  1398.    return( len == 0 );
  1399. }
  1400.  
  1401.  
  1402. /*
  1403.  * Name:    page_up
  1404.  * Purpose: To move the cursor one page up the window
  1405.  * Date:    June 5, 1991
  1406.  * Passed:  window:  pointer to current window
  1407.  * Notes:   The cursor line is moved back the required number of lines
  1408.  *           towards the start of the file.
  1409.  *          If the start of the file is reached, then movement stops.
  1410.  */
  1411. int  page_up( TDE_WIN *window )
  1412. {
  1413. int  i;                 /* count of lines scanned */
  1414. int  rc = OK;           /* default return code */
  1415. register TDE_WIN *win;   /* put window pointer in a register */
  1416. long number;
  1417. long len;
  1418.  
  1419.    win = window;
  1420.    entab_linebuff( );
  1421.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1422.       return( ERROR );
  1423.    if (win->rline != (win->cline - (win->top_line + win->ruler - 1))) {
  1424.       i = win->cline - (win->top_line + win->ruler - 1);
  1425.       number = win->rline;
  1426.       if (( win->rline - i) < win->page)
  1427.          win->rline = (win->cline-(win->top_line + win->ruler -1)) + win->page;
  1428.       win->rline -= win->page;
  1429.       for (len =0, i=(int)(number - win->rline); i>0; i--)
  1430.          if (win->ll->prev != NULL) {
  1431.             win->ll = win->ll->prev;
  1432.             len -= win->ll->len;
  1433.          }
  1434.       win->file_info->dirty = LOCAL;
  1435.       win->bin_offset += len;
  1436.    } else
  1437.       rc = ERROR;
  1438.    cursor_sync( win );
  1439.    return( rc );
  1440. }
  1441.  
  1442.  
  1443. /*
  1444.  * Name:    page_down
  1445.  * Purpose: To move the cursor one page down the window
  1446.  * Date:    June 5, 1991
  1447.  * Passed:  window:  pointer to current window
  1448.  * Notes:   The cursor line is moved forwards the required number of lines
  1449.  *           towards the end of the file.
  1450.  *          If the end of the file is reached, then movement stops.
  1451.  */
  1452. int  page_down( TDE_WIN *window )
  1453. {
  1454. int  i;                 /* count of lines scanned so far */
  1455. int  k;
  1456. int  rc = OK;
  1457. long len;
  1458. register TDE_WIN *win;  /* put window pointer in a register */
  1459. line_list_ptr p;
  1460.  
  1461.    win = window;
  1462.    entab_linebuff( );
  1463.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1464.       return( ERROR );
  1465.    p = win->ll;
  1466.    k = win->cline - (win->top_line + win->ruler);
  1467.    for (len=i=0; i < win->page && p->next != NULL; i++, k++, p=p->next)
  1468.       if (p->len != EOF)
  1469.          len += p->len;
  1470.    if (k >= win->page) {
  1471.       win->rline += i;
  1472.       win->cline = win->cline + i - win->page;
  1473.       win->bin_offset += len;
  1474.       win->ll = p;
  1475.       win->file_info->dirty = LOCAL;
  1476.    } else
  1477.       rc = ERROR;
  1478.    cursor_sync( win );
  1479.    return( rc );
  1480. }
  1481.  
  1482.  
  1483. /*
  1484.  * Name:    scroll_down
  1485.  * Purpose: scroll window down one line
  1486.  * Date:    June 5, 1991
  1487.  * Passed:  window:  pointer to current window
  1488.  * Notes:   If there is a line to scroll_down, make the window LOCAL dirty.
  1489.  *          We have to redraw the screen anyway, so don't update here.
  1490.  */
  1491. int  scroll_down( TDE_WIN *window )
  1492. {
  1493. int  rc = OK;
  1494. register TDE_WIN *win;   /* put window pointer in a register */
  1495.  
  1496.    win = window;
  1497.    entab_linebuff( );
  1498.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1499.       return( ERROR );
  1500.    if (win->cline == win->top_line + win->ruler) {
  1501.       if (win->ll->next != NULL) {
  1502.          ++win->rline;
  1503.          win->bin_offset += win->ll->len;
  1504.          win->ll = win->ll->next;
  1505.          win->file_info->dirty = LOCAL;
  1506.       } else
  1507.          rc = ERROR;
  1508.    } else {
  1509.       --win->cline;
  1510.       win->file_info->dirty = LOCAL;
  1511.    }
  1512.    cursor_sync( win );
  1513.    return( rc );
  1514. }
  1515.  
  1516.  
  1517. /*
  1518.  * Name:    scroll_up
  1519.  * Purpose: To scroll the window up one line
  1520.  * Date:    June 5, 1991
  1521.  * Passed:  window:  pointer to current window
  1522.  * Notes:   If this is the first page, then update screen here.  Else, make
  1523.  *           the window LOCAL dirty because we have to redraw screen.
  1524.  */
  1525. int  scroll_up( TDE_WIN *window )
  1526. {
  1527. int  rc = OK;
  1528. register TDE_WIN *win;   /* put window pointer in a register */
  1529.  
  1530.    win = window;
  1531.    entab_linebuff( );
  1532.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1533.       return( ERROR );
  1534.    if (win->rline > 1) {
  1535.       if (win->rline == (win->cline - (win->top_line + win->ruler - 1))) {
  1536.          if (!mode.sync)
  1537.             update_line( win );
  1538.          win->ll = win->ll->prev;
  1539.          win->bin_offset -= win->ll->len;
  1540.          --win->rline;
  1541.          --win->cline;
  1542.          if (!mode.sync)
  1543.             show_curl_line( win );
  1544.       } else {
  1545.          if (win->cline == win->bottom_line) {
  1546.             --win->rline;
  1547.             win->ll = win->ll->prev;
  1548.             win->bin_offset -= win->ll->len;
  1549.             win->file_info->dirty = LOCAL;
  1550.          } else {
  1551.             ++win->cline;
  1552.             win->file_info->dirty = LOCAL;
  1553.          }
  1554.       }
  1555.    } else
  1556.      rc = ERROR;
  1557.    cursor_sync( win );
  1558.    return( rc );
  1559. }
  1560.  
  1561.  
  1562. /*
  1563.  * Name:    pan_up
  1564.  * Purpose: To leave cursor on same logical line and scroll text up
  1565.  * Date:    September 1, 1991
  1566.  * Passed:  window:  pointer to current window
  1567.  * Notes:   If cursor is on first page then do not scroll.
  1568.  */
  1569. int  pan_up( TDE_WIN *window )
  1570. {
  1571. int  rc = OK;
  1572. register TDE_WIN *win;   /* put window pointer in a register */
  1573.  
  1574.    win = window;
  1575.    entab_linebuff( );
  1576.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1577.       return( ERROR );
  1578.  
  1579.    /*
  1580.     * see if cursor is on the first page. if it's not then pan_up.
  1581.     */
  1582.    if (win->rline != (win->cline+1 - (win->top_line + win->ruler))) {
  1583.       if (win->rline > 1) {
  1584.          --win->rline;
  1585.          win->ll = win->ll->prev;
  1586.          win->bin_offset -= win->ll->len;
  1587.          win->file_info->dirty = LOCAL;
  1588.       }
  1589.    } else
  1590.       rc = ERROR;
  1591.    cursor_sync( win );
  1592.    return( rc );
  1593. }
  1594.  
  1595.  
  1596. /*
  1597.  * Name:    pan_down
  1598.  * Purpose: To leave cursor on same logical line and scroll text down
  1599.  * Date:    September 1, 1991
  1600.  * Passed:  window:  pointer to current window
  1601.  * Notes:   If cursor is on last line in file then do not scroll.
  1602.  */
  1603. int  pan_down( TDE_WIN *window )
  1604. {
  1605. int  rc = OK;
  1606. register TDE_WIN *win;   /* put window pointer in a register */
  1607.  
  1608.    win = window;
  1609.    entab_linebuff( );
  1610.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1611.       return( ERROR );
  1612.    if (win->ll->len != EOF) {
  1613.       ++win->rline;
  1614.       win->bin_offset += win->ll->len;
  1615.       win->ll = win->ll->next;
  1616.       win->file_info->dirty = LOCAL;
  1617.    } else
  1618.       rc = ERROR;
  1619.    cursor_sync( win );
  1620.    return( rc );
  1621. }
  1622.  
  1623.  
  1624. /*
  1625.  * Name:    show_window_header
  1626.  * Purpose: show file stuff in window header
  1627.  * Date:    June 5, 1991
  1628.  * Passed:  window:  pointer to current window
  1629.  * Notes:   Clear line and display header in a lite bar
  1630.  */
  1631. void show_window_header( TDE_WIN *window )
  1632. {
  1633. register TDE_WIN *win;          /* put window pointer in a register */
  1634. int  len;
  1635. char temp[MAX_COLS+2];
  1636.  
  1637.    win = window;
  1638.    len = win->vertical ? win->end_col + 1 - win->start_col : win->end_col;
  1639.  
  1640.    assert( len >= 0 );
  1641.    assert( len <= g_display.ncols );
  1642.    memset( temp, ' ', len );
  1643.    temp[len] = '\0';
  1644.    s_output( temp, win->top_line-1, win->start_col, g_display.head_color );
  1645.    show_window_number_letter( win );
  1646.    show_window_fname( win );
  1647.    show_crlf_mode( win );
  1648.    show_size( win );
  1649.    show_line_col( win );
  1650. }
  1651.  
  1652.  
  1653. /*
  1654.  * Name:    show_window_number_letter
  1655.  * Purpose: show file number and letter of window in lite bar
  1656.  * Date:    June 5, 1991
  1657.  * Passed:  window:  pointer to current window
  1658.  */
  1659. void show_window_number_letter( TDE_WIN *window )
  1660. {
  1661. int  col;
  1662. char temp[10];
  1663. register TDE_WIN *win;   /* put window pointer in a register */
  1664.  
  1665.    win = window;
  1666.    col = win->start_col;
  1667.    s_output( "   ", win->top_line-1, col, g_display.head_color );
  1668.    my_ltoa( win->file_info->file_no, temp, 10 );
  1669.    s_output( temp, win->top_line-1, strlen( temp ) > 1 ? col : col+1,
  1670.              g_display.head_color );
  1671.    c_output( win->letter, col+2, win->top_line-1, g_display.head_color );
  1672. }
  1673.  
  1674.  
  1675. #if defined( __UNIX__ )
  1676. /*
  1677.  **********************************************************************
  1678.  ******************************  PART 1  ******************************
  1679.  **********************************************************************
  1680.  *
  1681.  * Let's try to make unix have the look and feel of a PC.
  1682.  */
  1683.  
  1684.  
  1685. /*
  1686.  * Name:     show_window_fname
  1687.  * Purpose:  show file name in window header.
  1688.  * Date:     June 5, 1991
  1689.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1690.  * Passed:   window:  pointer to current window
  1691.  * Notes:    Clear name field and display name in a lite bar
  1692.  */
  1693. void show_window_fname( TDE_WIN *window )
  1694. {
  1695. register int  fattr;
  1696. char *p;
  1697. register TDE_WIN *win;          /* put window pointer in a register */
  1698. int  col;
  1699. int  len;
  1700. char temp[PATH_MAX+2];
  1701.  
  1702.    win = window;
  1703.    col = win->start_col;
  1704.    len = win->vertical ? 11 : FNAME_LENGTH;
  1705.  
  1706.    assert( len >= 0 );
  1707.    assert( len <= g_display.ncols );
  1708.  
  1709.    memset( temp, ' ', len );
  1710.    temp[len] = '\0';
  1711.    s_output( temp, win->top_line-1, col+5, g_display.head_color );
  1712.  
  1713.    assert( strlen( win->file_info->file_name ) < (size_t)g_display.ncols );
  1714.  
  1715.    strcpy( temp, win->file_info->file_name );
  1716.    p = temp;
  1717.    len = strlen( temp );
  1718.    if (win->vertical) {
  1719.       for (p = temp + len; *(p-1) != '\\' && p>temp; )
  1720.          --p;
  1721.       if (strlen( p ) > 11)
  1722.          *(p + 11) = '\0';
  1723.    } else {
  1724.       if (len > FNAME_LENGTH)
  1725.          p = temp + len - (FNAME_LENGTH-1);
  1726.    }
  1727.    s_output( p, win->top_line-1, col+5, g_display.head_color );
  1728.    if (!win->vertical) {
  1729.       fattr = win->file_info->file_attrib;
  1730.       p = temp;
  1731.       *p++ = (char)(fattr & S_IRUSR  ? L_UNIX_READ    : '-');
  1732.       *p++ = (char)(fattr & S_IWUSR  ? L_UNIX_WRITE   : '-');
  1733.       *p++ = (char)(fattr & S_IXUSR  ? L_UNIX_EXECUTE : '-');
  1734.       *p   = '\0';
  1735.       s_output( temp, win->top_line-1, col+51, g_display.head_color );
  1736.    }
  1737. }
  1738.  
  1739. #else
  1740. /*
  1741.  **********************************************************************
  1742.  ******************************  PART 2  ******************************
  1743.  **********************************************************************
  1744.  *
  1745.  * Calls to BIOS and writes to PC hardware.
  1746.  */
  1747.  
  1748.  
  1749. /*
  1750.  * Name:     show_window_fname
  1751.  * Purpose:  show file name in window header.
  1752.  * Date:     June 5, 1991
  1753.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1754.  * Passed:   window:  pointer to current window
  1755.  * Notes:    Clear name field and display name in a lite bar
  1756.  */
  1757. void show_window_fname( TDE_WIN *window )
  1758. {
  1759. register int  fattr;
  1760. char *p;
  1761. register TDE_WIN *win;          /* put window pointer in a register */
  1762. int  col;
  1763. int  len;
  1764. char temp[MAX_COLS+2];
  1765.  
  1766.    win = window;
  1767.    col = win->start_col;
  1768.    len = win->vertical ? 11 : FNAME_LENGTH;
  1769.  
  1770.    assert( len >= 0 );
  1771.    assert( len <= g_display.ncols );
  1772.  
  1773.    memset( temp, ' ', len );
  1774.    temp[len] = '\0';
  1775.    s_output( temp, win->top_line-1, col+5, g_display.head_color );
  1776.  
  1777.    assert( strlen( win->file_info->file_name ) < (size_t)g_display.ncols );
  1778.  
  1779.    strcpy( temp, win->file_info->file_name );
  1780.    p = temp;
  1781.    if (win->vertical) {
  1782.       len = strlen( temp );
  1783.       for (p = temp + len; *(p-1) != ':' && *(p-1) != '\\' && p>temp; )
  1784.          --p;
  1785.    } else {
  1786.       temp[FNAME_LENGTH] = '\0';
  1787.       p = temp;
  1788.    }
  1789.    s_output( p, win->top_line-1, col+5, g_display.head_color );
  1790.    if (!win->vertical) {
  1791.       fattr = win->file_info->file_attrib;
  1792.       p = temp;
  1793.       *p++ = (char)(fattr & ARCHIVE   ? L_DOS_ARCHIVE   : '-');
  1794.       *p++ = (char)(fattr & SYSTEM    ? L_DOS_SYSTEM    : '-');
  1795.       *p++ = (char)(fattr & HIDDEN    ? L_DOS_HIDDEN    : '-');
  1796.       *p++ = (char)(fattr & READ_ONLY ? L_DOS_READ_ONLY : '-');
  1797.       *p   = '\0';
  1798.       s_output( temp, win->top_line-1, col+51, g_display.head_color );
  1799.    }
  1800. }
  1801.  
  1802. #endif
  1803.  
  1804. /*
  1805.  * Name:     show_crlf_mode
  1806.  * Purpose:  display state of crlf flag
  1807.  * Date:     June 5, 1991
  1808.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1809.  */
  1810. void show_crlf_mode( TDE_WIN *window )
  1811. {
  1812. char temp[MAX_COLS+2];
  1813.  
  1814.    if (!window->vertical) {
  1815.       switch (window->file_info->crlf) {
  1816.          case LF :
  1817.             strcpy( temp, mode_lf );
  1818.             break;
  1819.          case CRLF :
  1820.             strcpy( temp, mode_crlf );
  1821.             break;
  1822.          case BINARY :
  1823.             strcpy( temp, mode_bin );
  1824.             break;
  1825.          default :
  1826.             assert( FALSE );
  1827.       }
  1828.       s_output( temp, window->top_line-1, window->start_col+56,
  1829.                 g_display.head_color );
  1830.    }
  1831. }
  1832.  
  1833.  
  1834. /*
  1835.  * Name:    show_size
  1836.  * Purpose: show number of lines in file
  1837.  * Date:    June 5, 1991
  1838.  * Passed:  window:  pointer to current window
  1839.  */
  1840. void show_size( TDE_WIN *window )
  1841. {
  1842. char csize[20];
  1843.  
  1844.    if (!window->vertical  &&  window->file_info->crlf != BINARY) {
  1845.       s_output( "       ", window->top_line-1, 61, g_display.head_color );
  1846.       my_ltoa( window->file_info->length, csize, 10 );
  1847.       s_output( csize, window->top_line-1, 61, g_display.head_color );
  1848.    }
  1849. }
  1850.  
  1851.  
  1852. /*
  1853.  * Name:    quit
  1854.  * Purpose: To close the current window without saving the current file.
  1855.  * Date:    June 5, 1991
  1856.  * Passed:  window:  pointer to current window
  1857.  * Notes:   If the file has been modified but not saved, then the user is
  1858.  *           given a second chance before the changes are discarded.
  1859.  *          Note that this is only necessary if this is the last window
  1860.  *           that refers to the file.  If another window still refers to
  1861.  *           the file, then the check can be left until later.
  1862.  */
  1863. int  quit( TDE_WIN *window )
  1864. {
  1865. int  prompt_line;
  1866. register file_infos *file;
  1867. TDE_WIN *wp;
  1868. int  count = 0;
  1869. int  rc = OK;
  1870. #if defined( __UNIX__ )
  1871.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  1872. #else
  1873.  char display_buff[(MAX_COLS+2)*2];
  1874. #endif
  1875.  
  1876.    entab_linebuff( );
  1877.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  1878.       return( ERROR );
  1879.    prompt_line = window->bottom_line;
  1880.    file = window->file_info;
  1881.    for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  1882.       if (wp->file_info == file && wp->visible)
  1883.          ++count;
  1884.    }
  1885.    if (file->modified && count == 1) {
  1886.       save_screen_line( 0, prompt_line, display_buff );
  1887.       /*
  1888.        * abandon changes (y/n)
  1889.        */
  1890.       set_prompt( utils12, prompt_line );
  1891.       if (get_yn( ) != A_YES)
  1892.          rc = ERROR;
  1893.       restore_screen_line( 0, prompt_line, display_buff );
  1894.    }
  1895.  
  1896.    /*
  1897.     * remove window, allocate screen lines to other windows etc
  1898.     */
  1899.    if (rc == OK)
  1900.       finish( window );
  1901.    return( OK );
  1902. }
  1903.  
  1904.  
  1905. /*
  1906.  * Name:    move_up
  1907.  * Purpose: To move the cursor up one line
  1908.  * Date:    June 5, 1991
  1909.  * Passed:  window:  pointer to current window
  1910.  * Notes:   If the cursor is at the top of the window, then the file must
  1911.  *           be scrolled down.
  1912.  */
  1913. int  move_up( TDE_WIN *window )
  1914. {
  1915. int  rc = OK;
  1916. register TDE_WIN *win;   /* put window pointer in a register */
  1917. int  at_top = FALSE;    /* is cline at top of screen? */
  1918.  
  1919.    win = window;
  1920.    entab_linebuff( );
  1921.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1922.       return( ERROR );
  1923.  
  1924.    /*
  1925.     * if no previous line, give up
  1926.     */
  1927.    if (win->rline > 1) {
  1928.       if (win->cline == win->top_line + win->ruler) {
  1929.          win->file_info->dirty = LOCAL;
  1930.          at_top = TRUE;
  1931.       }
  1932.       if (!at_top)
  1933.          update_line( win );
  1934.       --win->rline;             /* ALWAYS decrement line counter */
  1935.       win->ll = win->ll->prev;
  1936.       win->bin_offset -= win->ll->len;
  1937.       if (!at_top) {
  1938.          --win->cline;          /* we aren't at top of screen - so move up */
  1939.          show_curl_line( win );
  1940.       }
  1941.    } else
  1942.       rc = ERROR;
  1943.    cursor_sync( win );
  1944.    return( rc );
  1945. }
  1946.  
  1947.  
  1948. /*
  1949.  * Name:    move_down
  1950.  * Purpose: To move the cursor down one line
  1951.  * Date:    June 5, 1991
  1952.  * Passed:  window:  pointer to current window
  1953.  * Notes:   If the cursor is at the bottom of the window, then the file must
  1954.  *           be scrolled up.   If the cursor is at the bottom of the file,
  1955.  *           then scroll line up until it is at top of screen.
  1956.  */
  1957. int  move_down( TDE_WIN *window )
  1958. {
  1959. int  rc;
  1960.  
  1961.    rc = prepare_move_down( window );
  1962.    cursor_sync( window );
  1963.    return( rc );
  1964. }
  1965.  
  1966.  
  1967. /*
  1968.  * Name:    prepare_move_down
  1969.  * Purpose: Do the stuff needed to move the cursor down one line.
  1970.  * Date:    June 5, 1991
  1971.  * Passed:  window:  pointer to current window
  1972.  * Notes:   Put all the stuff needed to move the cursor down one line in
  1973.  *           one function, so several functions can use the guts of the
  1974.  *           algorithm.
  1975.  */
  1976. int  prepare_move_down( TDE_WIN *window )
  1977. {
  1978. int  rc = OK;
  1979. register TDE_WIN *win;   /* put window pointer in a register */
  1980. int  at_bottom = FALSE; /* is cline at bottom of screen */
  1981.  
  1982.    win = window;
  1983.    entab_linebuff( );
  1984.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1985.       return( ERROR );
  1986.    if (win->cline == win->bottom_line) {
  1987.       win->file_info->dirty = LOCAL;
  1988.       at_bottom = TRUE;
  1989.    }
  1990.    if (!at_bottom)
  1991.       update_line( win );
  1992.    if (win->ll->len != EOF) {
  1993.       win->bin_offset += win->ll->len;
  1994.       ++win->rline;             /* ALWAYS increment line counter */
  1995.       win->ll = win->ll->next;
  1996.       if (!at_bottom) {
  1997.          ++win->cline;          /* if not at bottom of screen move down */
  1998.          show_curl_line( win );
  1999.       }
  2000.    } else if (win->cline > win->top_line + win->ruler) {
  2001.       --win->cline;
  2002.       win->file_info->dirty = LOCAL;
  2003.       rc = ERROR;
  2004.    } else
  2005.       rc = ERROR;
  2006.    return( rc );
  2007. }
  2008.  
  2009.  
  2010. /*
  2011.  * Name:    move_left
  2012.  * Purpose: To move the cursor left one character
  2013.  * Date:    June 5, 1991
  2014.  * Passed:  window:  pointer to current window
  2015.  * Notes:   If the cursor is already at the left of the screen, then
  2016.  *           scroll horizontally if we're not at beginning of line.
  2017.  */
  2018. int  move_left( TDE_WIN *window )
  2019. {
  2020. int  new_ruler = FALSE;
  2021.  
  2022.    if (window->ccol > window->start_col) {
  2023.       show_ruler_char( window );
  2024.       --window->ccol;
  2025.       --window->rcol;
  2026.    } else if (window->ccol == window->start_col && window->rcol > 0) {
  2027.       --window->rcol;
  2028.       --window->bcol;
  2029.       window->file_info->dirty = LOCAL;
  2030.       new_ruler = TRUE;
  2031.    }
  2032.    cursor_sync( window );
  2033.    if (new_ruler) {
  2034.       make_ruler( window );
  2035.       show_ruler( window );
  2036.    }
  2037.    return( OK );
  2038. }
  2039.  
  2040.  
  2041. /*
  2042.  * Name:    move_right
  2043.  * Purpose: To move the cursor right one character
  2044.  * Date:    June 5, 1991
  2045.  * Passed:  window:  pointer to current window
  2046.  * Notes:   If the cursor is already at the right of the screen (logical
  2047.  *          column 80) then scroll horizontally right.
  2048.  */
  2049. int  move_right( TDE_WIN *window )
  2050. {
  2051. int  new_ruler = FALSE;
  2052.  
  2053.    if (window->rcol < g_display.line_length - 1) {
  2054.       if (window->ccol < window->end_col) {
  2055.          show_ruler_char( window );
  2056.          ++window->ccol;
  2057.          ++window->rcol;
  2058.       } else if (window->ccol == window->end_col) {
  2059.          ++window->rcol;
  2060.          ++window->bcol;
  2061.          window->file_info->dirty = LOCAL;
  2062.          new_ruler = TRUE;
  2063.       }
  2064.    }
  2065.    cursor_sync( window );
  2066.    if (new_ruler) {
  2067.       make_ruler( window );
  2068.       show_ruler( window );
  2069.    }
  2070.    return( OK );
  2071. }
  2072.  
  2073.  
  2074. /*
  2075.  * Name:    pan_left
  2076.  * Purpose: To pan the screen left one character
  2077.  * Date:    January 5, 1992
  2078.  * Passed:  window:  pointer to current window
  2079.  */
  2080. int  pan_left( TDE_WIN *window )
  2081. {
  2082. /*
  2083.  * if (window->bcol == 0) {
  2084.  *    if (window->ccol > window->start_col) {
  2085.  *       show_ruler_char( window );
  2086.  *       --window->ccol;
  2087.  *       --window->rcol;
  2088.  *    }
  2089.  * } else if (window->bcol > 0 ) {
  2090.  * * *  Scroll window left function:
  2091.  * * *      --window->bcol;
  2092.  * * *      if (window->ccol < g_display.ncols - 1)
  2093.  * * *         ++window->ccol;
  2094.  * * *      else
  2095.  * * *         --window->rcol;
  2096.  */
  2097.    if (window->bcol > 0 ) {
  2098.       --window->bcol;
  2099.       --window->rcol;
  2100.       window->file_info->dirty = LOCAL;
  2101.       make_ruler( window );
  2102.       show_ruler( window );
  2103.    }
  2104.    cursor_sync( window );
  2105.    return( OK );
  2106. }
  2107.  
  2108.  
  2109. /*
  2110.  * Name:    pan_right
  2111.  * Purpose: To pan the screen right one character
  2112.  * Date:    January 5, 1992
  2113.  * Passed:  window:  pointer to current window
  2114.  */
  2115. int  pan_right( TDE_WIN *window )
  2116. {
  2117.    if (window->rcol < g_display.line_length - 1) {
  2118. /*
  2119.  *      scroll screen right function:
  2120.  *      if (window->ccol > 0)
  2121.  *         --window->ccol;
  2122.  *      else
  2123.  *         ++window->rcol;
  2124.  */
  2125.       ++window->rcol;
  2126.       ++window->bcol;
  2127.       window->file_info->dirty = LOCAL;
  2128.       make_ruler( window );
  2129.       show_ruler( window );
  2130.    }
  2131.    cursor_sync( window );
  2132.    return( OK );
  2133. }
  2134.  
  2135.  
  2136. /*
  2137.  * Name:    word_left
  2138.  * Purpose: To move the cursor left one word
  2139.  * Date:    June 5, 1991
  2140.  * Passed:  window:  pointer to current window
  2141.  * Notes:   Words are considered strings of letters, numbers and underscores,
  2142.  *          which must be separated by other characters.
  2143.  */
  2144. int  word_left( TDE_WIN *window )
  2145. {
  2146. text_ptr p;             /* text pointer */
  2147. int  len;               /* length of current line */
  2148. int  rc;
  2149. int  tabs;
  2150. int  rcol;
  2151. register int r1;
  2152. long rline;
  2153. line_list_ptr ll;
  2154. TDE_WIN w;
  2155.  
  2156.    entab_linebuff( );
  2157.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2158.       return( ERROR );
  2159.    rc = OK;
  2160.    dup_window_info( &w, window );
  2161.    rline = window->rline;
  2162.    rcol  = window->rcol;
  2163.    ll = window->ll;
  2164.    if (ll->len != EOF) {
  2165.       p   = ll->line;
  2166.       len = ll->len;
  2167.  
  2168.       tabs = mode.inflate_tabs;
  2169.       r1 =  tabs ? entab_adjust_rcol( p, len, rcol ) : rcol;
  2170.  
  2171.       if (p != NULL  &&  r1 > 0  &&  r1 >= len  &&
  2172.                                       !myiswhitespc( *(p + len - 1) )) {
  2173.          r1 = len - 1;
  2174.          p += r1;
  2175.          for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2176.          ++r1;
  2177.          rcol = tabs ? detab_adjust_rcol( ll->line, r1 ) : r1;
  2178.          check_virtual_col( window, rcol, rcol );
  2179.          make_ruler( window );
  2180.          show_ruler( window );
  2181.       } else {
  2182.          r1 =  r1 >= len ? len-1 : r1;
  2183.          if (r1 >= 0)
  2184.             p += r1;
  2185.          if (p != NULL  &&  r1 > 0  &&  !myiswhitespc( *p )  &&
  2186.                                           !myiswhitespc( *(p-1) )) {
  2187.             for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2188.             ++r1;
  2189.             rcol = tabs ? detab_adjust_rcol( ll->line, r1 ) : r1;
  2190.             check_virtual_col( window, rcol, rcol );
  2191.             make_ruler( window );
  2192.             show_ruler( window );
  2193.          } else {
  2194.  
  2195.             /*
  2196.              * if we are on the first letter of a word, get off.
  2197.              */
  2198.             if (p != NULL)
  2199.                for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2200.  
  2201.             /*
  2202.              * go to the next line if word begins at 1st col in line.
  2203.              */
  2204.             if (r1 < 0) {
  2205.                if (ll->prev != NULL) {
  2206.                   --rline;
  2207.                   ll = ll->prev;
  2208.                   p = ll->line;
  2209.                   r1 = ll->len - 1;
  2210.                   if (r1 >= 0)
  2211.                      p += r1;
  2212.                } else
  2213.                   rc = ERROR;
  2214.             }
  2215.  
  2216.             /*
  2217.              * skip all blanks until we get to a previous word
  2218.              */
  2219.             while (rc == OK  &&  (p == NULL  ||  (p != NULL  &&
  2220.                                                   myiswhitespc( *p )))) {
  2221.                for (; r1 >= 0 && myiswhitespc( *p ); r1--, p--);
  2222.                if (r1 < 0) {
  2223.                   if (ll->prev != NULL) {
  2224.                      --rline;
  2225.                      ll = ll->prev;
  2226.                      p = ll->line;
  2227.                      r1 = ll->len - 1;
  2228.                      if (r1 >= 0)
  2229.                         p += r1;
  2230.                   } else
  2231.                      rc = ERROR;
  2232.                } else
  2233.                   break;
  2234.             }
  2235.  
  2236.             /*
  2237.              * now, find the beginning of the word.
  2238.              */
  2239.             if (rc == OK  &&  p != NULL) {
  2240.                for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2241.                r1++;
  2242.                bin_offset_adjust( window, rline );
  2243.                find_adjust( window, ll, rline, r1 );
  2244.                if (rline != w.rline && !window->file_info->dirty) {
  2245.                   update_line( &w );
  2246.                   show_curl_line( window );
  2247.                }
  2248.                make_ruler( window );
  2249.                show_ruler( window );
  2250.             } else
  2251.                rc = ERROR;
  2252.          }
  2253.       }
  2254.    } else
  2255.       rc = ERROR;
  2256.  
  2257.    cursor_sync( window );
  2258.    return( rc );
  2259. }
  2260.  
  2261.  
  2262. /*
  2263.  * Name:    word_right
  2264.  * Purpose: To move the cursor right one word
  2265.  * Date:    June 5, 1991
  2266.  * Passed:  window:  pointer to current window
  2267.  * Notes:   Words are considered strings of letters, numbers and underscores,
  2268.  *           which must be separated by other characters.
  2269.  */
  2270. int  word_right( TDE_WIN *window )
  2271. {
  2272. int  len;               /* length of current line */
  2273. text_ptr p;             /* text pointer */
  2274. int  rc;
  2275. int  tabs;
  2276. int  rcol;
  2277. register int r1;
  2278. TDE_WIN w;
  2279. line_list_ptr ll;
  2280. long rline;
  2281.  
  2282.    entab_linebuff( );
  2283.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2284.       return( ERROR );
  2285.    rc = OK;
  2286.    dup_window_info( &w, window );
  2287.    rline = window->rline;
  2288.    r1 = rcol = window->rcol;
  2289.    ll    = window->ll;
  2290.    if (ll->len != EOF) {
  2291.       p   = ll->line;
  2292.       len = ll->len;
  2293.  
  2294.       tabs = mode.inflate_tabs;
  2295.       r1   =  tabs ? entab_adjust_rcol( p, len, rcol ) : rcol;
  2296.  
  2297.       /*
  2298.        * if rcol is past EOL, move it to EOL
  2299.        */
  2300.       r1 =  r1 >= len ? len-1 : r1;
  2301.       if (r1 >= 0)
  2302.          p += r1;
  2303.  
  2304.       /*
  2305.        * if cursor is on a word, find end of word.
  2306.        */
  2307.       if (p != NULL)
  2308.          for (; r1 < len && !myiswhitespc( *p ); r1++, p++);
  2309.       else
  2310.          r1 = len;
  2311.  
  2312.       /*
  2313.        * go to the next line if word ends at eol.
  2314.        */
  2315.       if (r1 == len) {
  2316.          ++rline;
  2317.          ll = ll->next;
  2318.          if (ll->len != EOF) {
  2319.             p = ll->line;
  2320.             len = ll->len;
  2321.             r1 = 0;
  2322.          } else
  2323.             rc = ERROR;
  2324.       }
  2325.  
  2326.       /*
  2327.        * now, go forward thru the file looking for the first letter of word.
  2328.        */
  2329.       while (rc == OK && (p == NULL  ||  (p != NULL && myiswhitespc( *p )))) {
  2330.          for (; r1 < len && myiswhitespc( *p ); r1++, p++);
  2331.          if (r1 == len) {
  2332.             ++rline;
  2333.             ll = ll->next;
  2334.             if (ll->len != EOF) {
  2335.                p = ll->line;
  2336.                len = ll->len;
  2337.                r1 = 0;
  2338.             } else
  2339.                rc = ERROR;
  2340.          } else
  2341.             break;
  2342.       }
  2343.    } else
  2344.       rc = ERROR;
  2345.  
  2346.    if (rc == OK) {
  2347.       bin_offset_adjust( window, rline );
  2348.       find_adjust( window, ll, rline, r1 );
  2349.       make_ruler( window );
  2350.       show_ruler( window );
  2351.    }
  2352.  
  2353.    if (rline != w.rline && !window->file_info->dirty) {
  2354.       update_line( &w );
  2355.       show_curl_line( window );
  2356.    }
  2357.    cursor_sync( window );
  2358.    return( rc );
  2359. }
  2360.  
  2361.  
  2362. /*
  2363.  * Name:    next_dirty_line
  2364.  * Purpose: To move the cursor to the next dirty line, if it exists
  2365.  * Date:    April 1, 1993
  2366.  * Passed:  window:  pointer to current window
  2367.  */
  2368. int  next_dirty_line( TDE_WIN *window )
  2369. {
  2370. int  rc;
  2371. line_list_ptr ll;
  2372. long rline;
  2373. long bin_offset;       /* binary offset */
  2374. TDE_WIN w;
  2375.  
  2376.    entab_linebuff( );
  2377.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2378.       return( ERROR );
  2379.    rc = OK;
  2380.    dup_window_info( &w, window );
  2381.    rline = window->rline;
  2382.    ll = window->ll;
  2383.    bin_offset = window->bin_offset;
  2384.    if (ll->len != EOF) {
  2385.       while (rc == OK) {
  2386.          if (ll->len != EOF) {
  2387.             ++rline;
  2388.             bin_offset += ll->len;
  2389.             ll = ll->next;
  2390.             if (ll->dirty == TRUE)
  2391.                break;
  2392.          } else
  2393.             rc = ERROR;
  2394.       }
  2395.    } else
  2396.       rc = ERROR;
  2397.  
  2398.    if (rc == OK) {
  2399.       window->bin_offset = bin_offset;
  2400.       find_adjust( window, ll, rline, window->rcol );
  2401.       make_ruler( window );
  2402.       show_ruler( window );
  2403.    } else
  2404.       error( WARNING, window->bottom_line, utils16 );
  2405.  
  2406.    if (rline != w.rline && !window->file_info->dirty) {
  2407.       update_line( &w );
  2408.       show_curl_line( window );
  2409.    }
  2410.    cursor_sync( window );
  2411.    return( rc );
  2412. }
  2413.  
  2414.  
  2415. /*
  2416.  * Name:    prev_dirty_line
  2417.  * Purpose: To move the cursor to the prev dirty line, if it exists
  2418.  * Date:    April 1, 1993
  2419.  * Passed:  window:  pointer to current window
  2420.  */
  2421. int  prev_dirty_line( TDE_WIN *window )
  2422. {
  2423. int  rc;
  2424. line_list_ptr ll;
  2425. long rline;
  2426. long bin_offset;        /* binary offset */
  2427. TDE_WIN w;
  2428.  
  2429.    entab_linebuff( );
  2430.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2431.       return( ERROR );
  2432.    rc = OK;
  2433.    dup_window_info( &w, window );
  2434.    rline = window->rline;
  2435.    ll = window->ll;
  2436.    bin_offset = window->bin_offset;
  2437.    if (ll->prev != NULL) {
  2438.       while (rc == OK) {
  2439.          if (ll->prev != NULL) {
  2440.             --rline;
  2441.             ll = ll->prev;
  2442.             bin_offset -= ll->len;
  2443.             if (ll->dirty == TRUE)
  2444.                break;
  2445.          } else
  2446.             rc = ERROR;
  2447.       }
  2448.    } else
  2449.       rc = ERROR;
  2450.  
  2451.    if (rc == OK) {
  2452.       window->bin_offset = bin_offset;
  2453.       find_adjust( window, ll, rline, window->rcol );
  2454.       make_ruler( window );
  2455.       show_ruler( window );
  2456.    } else
  2457.       error( WARNING, window->bottom_line, utils16 );
  2458.  
  2459.    if (rline != w.rline && !window->file_info->dirty) {
  2460.       update_line( &w );
  2461.       show_curl_line( window );
  2462.    }
  2463.    cursor_sync( window );
  2464.    return( rc );
  2465. }
  2466.  
  2467.  
  2468. /*
  2469.  * Name:    center_window
  2470.  * Purpose: To place the current line or cursor in the center of a window.
  2471.  * Date:    June 5, 1991
  2472.  * Passed:  window:  pointer to current window
  2473.  */
  2474. int  center_window( TDE_WIN *window )
  2475. {
  2476. int  center;
  2477. int  center_line;
  2478. int  diff;
  2479. register file_infos *file;
  2480. register TDE_WIN *win;           /* put window pointer in a register */
  2481.  
  2482.    win = window;
  2483.    file = win->file_info;
  2484.    center = (win->bottom_line + 1 - win->top_line) / 2 - win->ruler;
  2485.    center_line = win->top_line + win->ruler + center;
  2486.    diff = center_line - win->cline;
  2487.    entab_linebuff( );
  2488.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2489.       return( ERROR );
  2490.    if (g_status.command == CenterWindow) {
  2491.       if (diff > 0) {
  2492.          if (win->rline + diff <= file->length) {
  2493.             update_line( win );
  2494.             win->cline += diff;
  2495.             win->rline += diff;
  2496.             for (; diff > 0; diff--) {
  2497.                win->bin_offset += win->ll->len;
  2498.                win->ll = win->ll->next;
  2499.             }
  2500.             show_curl_line( win );
  2501.          }
  2502.       } else if (diff < 0) {
  2503.          update_line( win );
  2504.          win->cline += diff;
  2505.          win->rline += diff;
  2506.          for (; diff < 0; diff++) {
  2507.             win->ll = win->ll->prev;
  2508.             win->bin_offset -= win->ll->len;
  2509.          }
  2510.          show_curl_line( win );
  2511.       }
  2512.    } else {
  2513.       if (diff > 0) {
  2514.          win->cline += diff;
  2515.          if ((long)(win->cline+1 - (win->top_line + win->ruler)) > win->rline)
  2516.             win->cline = (win->top_line + win->ruler) - 1 + (int)win->rline;
  2517.          file->dirty = LOCAL;
  2518.       } else if (diff < 0) {
  2519.          win->cline = win->cline + diff;
  2520.          file->dirty = LOCAL;
  2521.       }
  2522.    }
  2523.    if (g_status.command == CenterWindow  ||  g_status.command == CenterLine)
  2524.       cursor_sync( win );
  2525.    return( OK );
  2526. }
  2527.  
  2528.  
  2529. /*
  2530.  * Name:    horizontal_screen_right
  2531.  * Purpose: To move the cursor one screen to the right
  2532.  * Date:    September 13, 1991
  2533.  * Passed:  window:  pointer to current window
  2534.  * Notes:   Add 80 columns to the real cursor.  If the cursor is past the
  2535.  *          maximum line length then move it back.
  2536.  */
  2537. int  horizontal_screen_right( TDE_WIN *window )
  2538. {
  2539. int  col;
  2540.  
  2541.    col = window->rcol;
  2542.    col += (window->end_col + 1 - window->start_col);
  2543.    if (col < MAX_LINE_LENGTH) {
  2544.       window->rcol = col;
  2545.       window->bcol += (window->end_col + 1 - window->start_col);
  2546.       window->file_info->dirty = LOCAL;
  2547.       check_virtual_col( window, window->rcol, window->ccol );
  2548.       make_ruler( window );
  2549.       show_ruler( window );
  2550.    }
  2551.    cursor_sync( window );
  2552.    return( OK );
  2553. }
  2554.  
  2555.  
  2556. /*
  2557.  * Name:    horizontal_screen_left
  2558.  * Purpose: To move the cursor one screen to the left
  2559.  * Date:    September 13, 1991
  2560.  * Passed:  window:  pointer to current window
  2561.  * Notes:   Subtract screen width from the real cursor.  If the cursor is less
  2562.  *           than zero then see if bcol is zero.  If bcol is not zero then make
  2563.  *           bcol zero.
  2564.  */
  2565. int  horizontal_screen_left( TDE_WIN *window )
  2566. {
  2567. int  screen_width;
  2568.  
  2569.    screen_width = window->end_col + 1 - window->start_col;
  2570.    if (window->rcol - screen_width < 0) {
  2571.       if (window->bcol != 0) {
  2572.          window->bcol = 0;
  2573.          window->file_info->dirty = LOCAL;
  2574.       }
  2575.    } else {
  2576.       window->rcol -= screen_width;
  2577.       window->bcol -= screen_width;
  2578.       if (window->bcol < 0)
  2579.          window->bcol = 0;
  2580.       window->file_info->dirty = LOCAL;
  2581.    }
  2582.    check_virtual_col( window, window->rcol, window->ccol );
  2583.    cursor_sync( window );
  2584.    make_ruler( window );
  2585.    show_ruler( window );
  2586.    return( OK );
  2587. }
  2588.  
  2589.  
  2590. /*
  2591.  * Name:    goto_top_file
  2592.  * Purpose: To move the cursor to the top of the file.
  2593.  * Date:    June 5, 1991
  2594.  * Passed:  window:  pointer to current window
  2595.  */
  2596. int  goto_top_file( TDE_WIN *window )
  2597. {
  2598. register TDE_WIN *win;   /* put window pointer in a register */
  2599. long num;
  2600.  
  2601.    win = window;
  2602.    entab_linebuff( );
  2603.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2604.       return( ERROR );
  2605.    if (win->rline != win->cline - (win->top_line+win->ruler-1)) {
  2606.       win->bin_offset = 0;
  2607.       win->rline = win->cline - (win->top_line+win->ruler-1);
  2608.       win->ll = win->file_info->line_list;
  2609.       for (num=1; num < win->rline; num++) {
  2610.          win->bin_offset += win->ll->len;
  2611.          win->ll = win->ll->next;
  2612.       }
  2613.       display_current_window( win );
  2614.    }
  2615.    cursor_sync( win );
  2616.    return( OK );
  2617. }
  2618.  
  2619.  
  2620. /*
  2621.  * Name:    goto_end_file
  2622.  * Purpose: To move the cursor to the end of the file.
  2623.  * Date:    June 5, 1991
  2624.  * Passed:  window:  pointer to current window
  2625.  */
  2626. int  goto_end_file( TDE_WIN *window )
  2627. {
  2628. register TDE_WIN *win;  /* put window pointer in a register */
  2629. line_list_ptr ll;
  2630. long length;
  2631.  
  2632.    win = window;
  2633.    entab_linebuff( );
  2634.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2635.       return( ERROR );
  2636.    length = win->file_info->length;
  2637.    if (length > win->rline + win->bottom_line - win->cline) {
  2638.       win->rline = length - (win->bottom_line - win->cline) + 1;
  2639.       win->ll = win->file_info->line_list_end;
  2640.       for (;length >= win->rline; length--)
  2641.          win->ll = win->ll->prev;
  2642.  
  2643.       win->bin_offset = 0;
  2644.       ll = win->file_info->line_list;
  2645.       for (length = 1; length < win->rline; length++) {
  2646.          win->bin_offset += ll->len;
  2647.          ll = ll->next;
  2648.       }
  2649.  
  2650.       display_current_window( win );
  2651.    }
  2652.    cursor_sync( win );
  2653.    return( OK );
  2654. }
  2655.  
  2656.  
  2657. /*
  2658.  * Name:     goto_line
  2659.  * Purpose:  To move the cursor to a particular line in the file
  2660.  * Date:     June 5, 1991
  2661.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2662.  * Passed:   window:  pointer to current window
  2663.  */
  2664. int  goto_line( TDE_WIN *window )
  2665. {
  2666. long number;            /* line number selected */
  2667. long n;
  2668. register TDE_WIN *win;   /* put window pointer in a register */
  2669. line_list_ptr ll;
  2670. int  rc;
  2671. char answer[MAX_COLS+2];
  2672. char temp[MAX_COLS+2];
  2673.  
  2674.    win = window;
  2675.    entab_linebuff( );
  2676.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2677.       return( ERROR );
  2678.    /*
  2679.     * find out where we are going
  2680.     */
  2681.  
  2682.    answer[0] = '\0';
  2683.    /*
  2684.     * line number:
  2685.     */
  2686.    if (get_name( find11, win->bottom_line, answer,
  2687.                  g_display.message_color ) != OK  ||  *answer == '\0')
  2688.       return( ERROR );
  2689.    number = atol( answer );
  2690.  
  2691.    if (number > 0  && number <= (long)win->file_info->length) {
  2692.       update_line( win );
  2693.       ll = win->ll;
  2694.       n = win->rline;
  2695.       if (number < win->rline) {
  2696.          if (n - number < number - 1) {
  2697.             for (; n > number; n--) {
  2698.                ll = ll->prev;
  2699.                win->bin_offset -= ll->len;
  2700.             }
  2701.          } else {
  2702.             ll = win->file_info->line_list;
  2703.             n = 1;
  2704.             for (; n < number; n++) {
  2705.                win->bin_offset += ll->len;
  2706.                ll = ll->next;
  2707.             }
  2708.          }
  2709.       } else if (number > win->rline) {
  2710.          for (; n < number; n++) {
  2711.             win->bin_offset += ll->len;
  2712.             ll = ll->next;
  2713.          }
  2714.       }
  2715.       find_adjust( win, ll, number, win->rcol );
  2716.       if (!win->file_info->dirty)
  2717.          show_curl_line( win );
  2718.       rc = OK;
  2719.    } else {
  2720.       /*
  2721.        * out of range.  must be in the range 1 -
  2722.        */
  2723.       strcpy( temp, find12 );
  2724.       my_ltoa( win->file_info->length, temp + strlen( temp ), 10 );
  2725.       error( WARNING, win->bottom_line, temp );
  2726.       rc = ERROR;
  2727.    }
  2728.    return( rc );
  2729. }
  2730.  
  2731.  
  2732. /*
  2733.  * Name:    set_marker
  2734.  * Purpose: To set file marker
  2735.  * Date:    December 28, 1991
  2736.  * Passed:  window:  pointer to current window
  2737.  */
  2738. int  set_marker( TDE_WIN *window )
  2739. {
  2740. register MARKER  *marker;       /* put the marker in a register */
  2741.  
  2742.    marker = &window->file_info->marker[g_status.command - SetMark1];
  2743.    marker->rline  = window->rline;
  2744.    marker->rcol   = window->rcol;
  2745.    marker->ccol   = window->ccol;
  2746.    marker->bcol   = window->bcol;
  2747.    marker->marked = TRUE;
  2748.    return( OK );
  2749. }
  2750.  
  2751.  
  2752. /*
  2753.  * Name:     goto_marker
  2754.  * Purpose:  To goto a file marker
  2755.  * Date:     December 28, 1991
  2756.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2757.  * Passed:   window:  pointer to current window
  2758.  */
  2759. int  goto_marker( TDE_WIN *window )
  2760. {
  2761. int  m;
  2762. file_infos *file;
  2763. long new_rline;
  2764. long n;
  2765. MARKER *marker;
  2766. register TDE_WIN *win;   /* put window pointer in a register */
  2767. line_list_ptr ll;
  2768. int  rc;
  2769.  
  2770.    win = window;
  2771.    m = g_status.command - GotoMark1;
  2772.    file = win->file_info;
  2773.    marker = &file->marker[m];
  2774.    if (marker->marked) {
  2775.       entab_linebuff( );
  2776.       if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2777.          return( ERROR );
  2778.       file->dirty = LOCAL;
  2779.       if (marker->rline > file->length)
  2780.          marker->rline = file->length;
  2781.       if (marker->rline < 1l)
  2782.          marker->rline = 1l;
  2783.       new_rline = marker->rline;
  2784.       ll = win->ll;
  2785.       if (new_rline < win->rline) {
  2786.          if (win->rline - new_rline < new_rline - 1) {
  2787.             for (n=win->rline; n > new_rline; n--) {
  2788.                ll = ll->prev;
  2789.                win->bin_offset -= ll->len;
  2790.             }
  2791.          } else {
  2792.             ll = win->file_info->line_list;
  2793.             win->bin_offset = 0;
  2794.             n = 1;
  2795.             for (; n < new_rline; n++) {
  2796.                win->bin_offset += ll->len;
  2797.                ll = ll->next;
  2798.             }
  2799.          }
  2800.       } else if (new_rline > win->rline) {
  2801.          n = win->rline;
  2802.          for (; n < new_rline; n++) {
  2803.             win->bin_offset += ll->len;
  2804.             ll = ll->next;
  2805.          }
  2806.       }
  2807.       win->rline  = new_rline;
  2808.       win->ll     = ll;
  2809.       win->rcol   = marker->rcol;
  2810.       win->ccol   = marker->ccol;
  2811.       win->bcol   = marker->bcol;
  2812.       if (win->rline < (win->cline - ((win->top_line + win->ruler) - 1)))
  2813.          win->cline = (int)win->rline + (win->top_line + win->ruler) - 1;
  2814.       check_virtual_col( win, win->rcol, win->ccol );
  2815.       make_ruler( window );
  2816.       show_ruler( window );
  2817.       rc = OK;
  2818.    } else {
  2819.       if (m == 9)
  2820.          m = -1;
  2821.       *(utils13 + UTILS13_NO_SLOT) = (char)('0' + m + 1);
  2822.       /*
  2823.        * marker not set
  2824.        */
  2825.       error( WARNING, win->bottom_line, utils13 );
  2826.       rc = ERROR;
  2827.    }
  2828.    return( rc );
  2829. }
  2830.  
  2831.  
  2832. /*
  2833.  * Name:     date_time_stamp
  2834.  * Purpose:  put system date and time into file at cursor position
  2835.  * Date:     June 5, 1992
  2836.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2837.  * Passed:   window:  pointer to current window
  2838.  */
  2839. int  date_time_stamp( TDE_WIN *window )
  2840. {
  2841. char stuff[20];
  2842. register char *dt;
  2843. int  year, month, day;
  2844. int  hours, minutes;
  2845. int  one, two, three;
  2846. int  i;
  2847. int  pm;
  2848. char answer[MAX_COLS+2];
  2849.  
  2850.  
  2851.    get_date( &year, &month, &day, &i );
  2852.    get_time( &hours, &minutes, &i, &i );
  2853.    dt = answer;
  2854.  
  2855.    /*
  2856.     * mod year with 100 if needed.
  2857.     */
  2858.    switch (mode.date_style) {
  2859.       case MM_DD_YY  :
  2860.       case DD_MM_YY  :
  2861.       case YY_MM_DD  :
  2862.          year = year % 100;
  2863.    }
  2864.  
  2865.    switch (mode.date_style) {
  2866.       case DD_MM_YY   :
  2867.       case DD_MM_YYYY :
  2868.          one = day;
  2869.          two = month;
  2870.          three = year;
  2871.          break;
  2872.       case YY_MM_DD   :
  2873.       case YYYY_MM_DD :
  2874.          one = year;
  2875.          two = month;
  2876.          three = day;
  2877.          break;
  2878.       case MM_DD_YY   :
  2879.       case MM_DD_YYYY :
  2880.       default         :
  2881.          one = month;
  2882.          two = day;
  2883.          three = year;
  2884.          break;
  2885.    }
  2886.    strcpy( dt, my_ltoa( one, stuff, 10 ) );
  2887.    strcat( dt, "-" );
  2888.    strcat( dt, my_ltoa( two, stuff, 10 ) );
  2889.    strcat( dt, "-" );
  2890.    strcat( dt, my_ltoa( three, stuff, 10 ) );
  2891.  
  2892.    strcat( dt, "  " );
  2893.  
  2894.    pm = FALSE;
  2895.    if (mode.time_style == _12_HOUR) {
  2896.       if (hours >= 12 && hours < 24)
  2897.          pm = TRUE;
  2898.       if (hours < 1)
  2899.          hours = 12;
  2900.       else if (hours >= 13)
  2901.          hours -= 12;
  2902.    }
  2903.  
  2904.    if (hours < 1)
  2905.       strcat( dt, "0" );
  2906.    strcat( dt, my_ltoa( hours, stuff, 10 ) );
  2907.    strcat( dt, ":" );
  2908.    if (minutes < 10)
  2909.       strcat( dt, "0" );
  2910.    strcat( dt, my_ltoa( minutes, stuff, 10 ) );
  2911.    if (mode.time_style == _12_HOUR)
  2912.       strcat( dt, pm == FALSE ? time_am : time_pm );
  2913.    strcat( dt, "  " );
  2914.    return( add_chars( dt, window ) );
  2915. }
  2916.  
  2917.  
  2918. /*
  2919.  * Name:    add_chars
  2920.  * Purpose: insert string into file
  2921.  * Date:    June 5, 1992
  2922.  * Passed:  string:  string to add to file
  2923.  *          window:  pointer to current window
  2924.  */
  2925. int  add_chars( char *string, TDE_WIN *window )
  2926. {
  2927. int  rc = OK;
  2928.  
  2929.    while (*string) {
  2930.       g_status.key_pressed = *string;
  2931.       rc = insert_overwrite( window );
  2932.       ++string;
  2933.    }
  2934.    return( rc );
  2935. }
  2936.