#module NEWSHELP "V5.6"

/*
**++
**  FACILITY:
**
**      NEWSHELP
**
**  ABSTRACT:
**
**      This module displays the NEWS help library on the screen using
**      SMG as the presentation manager
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V5.5     7-Oct-1988     GIH
**          Make the help display scrollable.
**
**      V5.6    11-Nov-1988     GIH
**          Correct bug with up arrow performing prev-screen
**--
**/

#include "newsinclude.h"
#include "newsdefine.h"
#include "newsextern.h"

#define HELP_DISP_SIZE 500

static int vd_created = 0,
           help_top_paste = 3,
           help_bot_paste = 4 - HELP_DISP_SIZE,
           help_cur_paste,
           start_itm,
           help_lines,
           disp_top,
           disp_bot,
           hhid,
           htid;

/*
 *  hlp_output
 *
 *  Place a line on the display - if this causes scrolling, move the display
 *  so as to maintain the item start line at the top of the display window
 */

static hlp_output(out_str)
    struct dsc$descriptor *out_str;
{
    int cols;
    smg$put_with_scroll(&htid,out_str,0,0,0,0,0);
    smg$return_cursor_pos(&htid,&help_lines,&cols);
    if (help_lines >= HELP_DISP_SIZE) {
        if (start_itm) {
            --start_itm;
            if (help_cur_paste < 3) {
                --disp_top;
                --disp_bot;
                ++help_cur_paste;
                smg$move_virtual_display(&htid,&pid,&help_cur_paste,c$rfi(1),0);
                }
            }
        }
    return(1);
}

/*
 *  hlp_input
 *
 *  Get the text corresponding to the help prompt. Allow the screen to
 *  be scrolled using the screen movement keys
 */

hlp_input(get_str,prompt_str,out_len)
    struct dsc$descriptor *get_str,
                          *prompt_str;
    unsigned short *out_len;
{
    int screen_size = (devrow - 4),
        status,
        n,
        act,
        repeat;
    char mprompt[80],
         get_line[80],
         resp[132];
    unsigned short trm;
    $DESCRIPTOR(get,get_line);

    for (;;) {
        act = 0;
        brdcst_col = 7;
        display_brdcst(3);
        brdcst_line = 3;
        if (help_lines > disp_bot) {
            strcpy(mprompt,"<RETURN for more>");
            smg$put_chars(&trailer_vd,c$dsc(mprompt),c$rfi(2),c$rfi(1),c$rfi(1),c$rfi(SMG$M_REVERSE),0,0);
            }
        else smg$erase_line(&trailer_vd,c$rfi(2),c$rfi(1));
        smg$erase_line(&trailer_vd,c$rfi(1),c$rfi(1));
        smg$set_cursor_abs(&trailer_vd,c$rfi(1),c$rfi(1));
        smg$end_pasteboard_update(&pid);
        smg$repaint_line(&pid,c$rfi(devrow-2),c$rfi(1));
        status = smg$read_composed_line(&kid,&keytab,&get,prompt_str,out_len,(screen_active ? &trailer_vd : 0),0,0,0,0,0,&trm);
        brdcst_line = 0;
        clear_err_line();
        smg$begin_pasteboard_update(&pid);
        if (status == SMG$_EOF) status = RMS$_EOF;
        if (status == RMS$_EOF) return(status);
        get_line[*out_len] = '\0';
        strcpy(response,get_line);
        strncpy(get_str->dsc$a_pointer,get_line,*out_len);
        if ((help_lines > disp_bot) && !*out_len) trm = SMG$K_TRM_NEXT_SCREEN;
        if (trm == SMG$K_TRM_CTRLW) do_refresh();
        else if ((!strcmp(get_line," ")) ||
                 (trm == SMG$K_TRM_NEXT_SCREEN) ||
                 (trm == SMG$K_TRM_DOWN)) {
            if (!strcmp(get_line," ")) n = screen_size;
            else {
                if (!*response) repeat = 1;
                else if (!sscanf(response,"%d",&repeat)) repeat = 1;
                if (!strcmp(response,"BOTTOM")) repeat = 1000;
                if (trm == SMG$K_TRM_DOWN) n = repeat;
                else n = screen_size * repeat;
                }
            if (n < (screen_size + 2)) {
                smg$end_pasteboard_update(&pid);
                act = 1;
                }
            while (n) {
                if ((help_cur_paste == help_bot_paste) 
                    || (help_lines <= disp_bot)) break;
                --help_cur_paste;
                ++disp_top;
                ++disp_bot;
                smg$move_virtual_display(&htid,&pid,&help_cur_paste,c$rfi(1),0);
                --n;
                }
            if (act) smg$begin_pasteboard_update(&pid);
            act = 0;
            }
        else if ((trm == SMG$K_TRM_PREV_SCREEN) ||
                 (trm == SMG$K_TRM_UP)) {
            if (!sscanf(response,"%d",&repeat)) repeat = 1;
            if (!strcmp(response,"TOP")) repeat = 1000;
            if (trm == SMG$K_TRM_UP) n = repeat;
            else n = screen_size * repeat;
            if (n < (screen_size + 2)) {
                smg$end_pasteboard_update(&pid);
                act = 1;
                }
            while (n) {
                if (help_cur_paste == help_top_paste) {
                    err_line("\tTop of Display\n");
                    break;
                    }
                --disp_top;
                --disp_bot;
                ++help_cur_paste;
                smg$move_virtual_display(&htid,&pid,&help_cur_paste,c$rfi(1),0);
                --n;
                }
            if (act) smg$begin_pasteboard_update(&pid);
            act = 0;
            }
        else if (!*out_len) {
            smg$erase_line(&trailer_vd,c$rfi(1),c$rfi(1));
            return(status);
            }
        else {
            start_itm = help_lines;
            help_cur_paste = help_top_paste - start_itm;
            disp_top = start_itm;
            disp_bot = start_itm + devrow - 6;
            smg$move_virtual_display(&htid,&pid,&help_cur_paste,c$rfi(1),0);
            strncpy(resp,prompt_str->dsc$a_pointer,prompt_str->dsc$w_length);
            resp[prompt_str->dsc$w_length] ='\0';
            strcat(resp," ");
            strcat(resp,response);
            hlp_output(c$dsc(resp));
            smg$erase_line(&trailer_vd,c$rfi(1),c$rfi(1));
            return(status);
            }
        }
}

/*
 *  do_help
 *
 *  Enter the help utility to interactively display all help on a module.
 */

call_help(hlpline)
    char *hlpline;
{
    int line_len = devcol,
        LIB$PUT_OUTPUT(),
        LIB$GET_INPUT();
    static $DESCRIPTOR(lib_dsc, HELP_FILE);

    if (!hlpline || !*hlpline) hlpline = "NEWS";

    if (screen_active) {
        if (!vd_created++) {
            smg$create_virtual_display(c$rfi(HELP_DISP_SIZE + devrow),&devcol,&htid,0,0,0);
            smg$set_display_scroll_region(&htid,c$rfi(1),c$rfi(HELP_DISP_SIZE));
            smg$create_virtual_display(c$rfi(2),c$rfi(80),&hhid,0,0,0);
            }
        smg$erase_display(&htid);
        smg$erase_display(&hhid);
        smg$put_chars(&hhid,c$dsc("NEWS Help DISPLAY"),c$rfi(1),c$rfi(1),0,c$rfi(SMG$M_BOLD),0,0);
        smg$paste_virtual_display(&htid,&pid,c$rfi(3),c$rfi(1));
        smg$paste_virtual_display(&hhid,&pid,c$rfi(1),c$rfi(1));
        smg$repaste_virtual_display(&trailer_vd,&pid,c$rfi(devrow - 2),c$rfi(1));
        start_itm = 1;
        help_cur_paste = 3;
        disp_top = 1;
        disp_bot = devrow - 5;
        help_lines = 0;
        lbr$output_help(hlp_output,&line_len,c$dsc(hlpline),&lib_dsc, HLP$V_PROMPT, hlp_input);
        smg$erase_line(&trailer_vd,c$rfi(1),c$rfi(1));
        smg$end_pasteboard_update(&pid);
        smg$repaint_line(&pid,c$rfi(devrow-2),c$rfi(1));
        smg$begin_pasteboard_update(&pid);
        smg$unpaste_virtual_display(&hhid,&pid);
        smg$unpaste_virtual_display(&htid,&pid);
        }
    else lbr$output_help(LIB$PUT_OUTPUT, &line_len,c$dsc(hlpline),&lib_dsc, HLP$V_PROMPT, LIB$GET_INPUT);
    return(0);
}

do_help()
{
    char rol[132],
         hlpline[132];
    short rol_len;
    $DESCRIPTOR(rol_dsc,rol);

    strcpy(hlpline,"NEWS");
    if (cli$get_value(c$dsc("TOPIC"),&rol_dsc,&rol_len) & 1) {
        rol[rol_len] = '\0';
        strcat(hlpline," ");
        strcat(hlpline,rol);
        }
    return(call_help(hlpline),0);
}
