Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-03 - decus/20-0078/libsim/form.sim
There are 4 other files named form.sim in the archive. Click here to see a list.
OPTIONS(/e/l);
EXTERNAL CHARACTER PROCEDURE fetchar, getch;
EXTERNAL INTEGER PROCEDURE trmop, gettab, checkreal, checkint;
EXTERNAL PROCEDURE depchar, echo, abort, outchr, forceout, outstring;
EXTERNAL TEXT PROCEDURE frontstrip, upcase, storbokstav, tmpin, scanto;
EXTERNAL BOOLEAN PROCEDURE tmpout, meny;
EXTERNAL CLASS vista, termty;
vista CLASS form;
NOT HIDDEN PROTECTED myinimage, show_page, ask_page, field,
intfield, realfield, choicefield, alphafield, first_field,
stopasking;
NOT HIDDEN height, echon, echoff, terminaltype,
resume_display, cancel_display, start_blink, stop_blink,
cause_real_time_delay, get_char_from_screen,
synchronize, restore_the_whole_screen,
home_the_cursor, set_char_on_screen,
outchar, blank_line, outimage, outtext, make_blank,
outfix, outreal, outint,
restore_one_char,
insingle, inimage, inint, inreal,
inword, inyes, move_the_cursor_to, blank_the_screen,
stopblink, startblink,
horizontalpos, verticalpos,
up, down, left, right, altmode,
carriagereturn, linefeed, home, fill,
null, tab, formfeed, verttab,
controlchar, screen, echoenabled;
BEGIN
  REF (field) last_field, first_field, main_field,
  temp_field;
  BOOLEAN error_is_blinking, got_movechar, stopask,
  last_is_controlchar;
  INTEGER errmesslength, i, line, order, cover_length;
  CHARACTER c, movechar; TEXT temp_answer;

  PROCEDURE stopasking; stopask:= TRUE;


  PROCEDURE myinimage(length, stopchar);
  INTEGER length; CHARACTER stopchar;
  BEGIN
    BOOLEAN nostopchar; INTEGER count, firstpos;
    firstpos:= horizontalpos;
    sysin.image:= NOTEXT;
    sysin.image.setpos(1);
    WHILE TRUE DO
    BEGIN
      IF count > length THEN GOTO out;
      c:= insingle(TRUE);
      IF NOT nostopchar THEN
      nostopchar:= stopchar NE c ELSE IF c = stopchar THEN
      GOTO out;
      IF NOT controlchar AND c NE fill THEN
      BEGIN
        sysin.image.putchar(c); count:= count+1;
        last_is_controlchar:= FALSE;
        IF c = '?' AND count = 1 THEN GOTO outfast;
      END ELSE
      BEGIN
                 IF c =
      carriagereturn THEN
      BEGIN insingle(TRUE);
        GOTO outfast;
      END;
      last_is_controlchar:= TRUE;
      BEGIN
        IF c NE fill THEN GOTO out;
        last_is_controlchar:= FALSE;
        IF horizontalpos < firstpos THEN
        move_the_cursor_to(firstpos,verticalpos);
        IF sysin.pos > 1 THEN
        BEGIN
          IF echoenabled THEN
          BEGIN
            IF count <= 0 THEN outchar(' ');
          END ELSE
          BEGIN
            sysin.setpos(sysin.pos-1);
            sysin.image.putchar(' ');
            sysin.setpos(sysin.pos-1);
          END;
          END;
        END;
      END;
    END;
    out: IF c NE tab THEN
    sysin.image.putchar(c);
    outfast: sysin.image.setpos(1);
  END;

  PROCEDURE show_page;
  BEGIN
    FOR temp_field:- first_field,
    temp_field.next WHILE temp_field =/= NONE DO
    INSPECT temp_field DO
    BEGIN
      putheader; answer:- NOTEXT;
    END;
  END;

  PROCEDURE ask_page;
  BEGIN
    loop: IF stopask THEN stopask:= FALSE ELSE
    FOR temp_field:- first_field,
    temp_field.next WHILE temp_field =/= NONE DO
    IF temp_field.answer = NOTEXT THEN
    BEGIN
      resume(temp_field);
      GOTO loop;
    END;
    sysout.breakoutimage;
  END;

  CLASS field(h,v,header,length,stopchar, helptext);
  VALUE header, helptext;
  INTEGER h, v, length; CHARACTER stopchar;
  TEXT header, helptext;
  VIRTUAL: PROCEDURE help;
  BEGIN
    TEXT answer; INTEGER orderinline;
    REF(field) next;

    PROCEDURE help;
    BEGIN
      IF helptext == NOTEXT THEN helptext:-
      copy("There is no HELP available here");
      blank_line(18);
      move_the_cursor_to(0,18); outtext(helptext); breakoutimage;
      error_is_blinking:= TRUE;
    END;

    PROCEDURE error(errmess); VALUE errmess; TEXT errmess;
    BEGIN
      move_the_cursor_to(0,18); start_blink;
      outtext("->"); stop_blink;
      outtext(errmess);
      error_is_blinking:= TRUE;
      errmesslength:= errmess.length;
      GOTO get_answer;
    END;

    PROCEDURE putheader;
    IF header =/= NOTEXT THEN
    BEGIN
      move_the_cursor_to(h,v); outtext(header);
    END;

    PROCEDURE screen_answer(answer);
    TEXT answer;
    COMMENT will put answer onto screen,
    covering cover_length chars;
    BEGIN
      move_the_cursor_to(h+header.length+1,v);
      outtext(answer);
      make_blank(length-answer.length);
    END;

    PROCEDURE change_answer(new_answer);
    VALUE new_answer; TEXT new_answer;
    BEGIN
      i:= answer.length;
      answer:- new_answer;
      screen_answer(answer);
    END;

    IF last_field =/= NONE THEN last_field.next:- THIS
    field;
    last_field:- THIS field;
    IF first_field == NONE THEN first_field:- THIS field;
    IF line NE v THEN
    BEGIN
      line:= v; order:= orderinline:= 1;
    END ELSE
    BEGIN orderinline:= order:= order+1;
    END;
    detach;
    get_answer:
    move_the_cursor_to(h+header.length+1,v);
    IF echoenabled THEN inimage ELSE
    myinimage(length,stopchar);
    temp_answer:- copy(frontstrip(sysin.image.strip));
    IF temp_answer = "?" THEN
    BEGIN help; GOTO get_answer;
    END;
    IF sysin.image.sub(1,1) = " " AND temp_answer =/= NOTEXT
    THEN screen_answer(temp_answer);
    movechar:= IF temp_answer == NOTEXT THEN ' ' ELSE
    temp_answer.sub(temp_answer.length,1).getchar;
    got_movechar:= IF last_is_controlchar THEN
    movechar = left OR movechar = right
    OR movechar = up OR movechar = down
    OR movechar = home ELSE FALSE;
    IF error_is_blinking THEN
    BEGIN
      blank_line(18); error_is_blinking:= FALSE;
      IF answer.length > temp_answer.length THEN
      BEGIN
        move_the_cursor_to(h+header.length+1
        +temp_answer.length-
        (IF got_movechar THEN 1 ELSE 0),v);
        cover_length:= answer.length-temp_answer.length
        +(IF got_movechar THEN 1 ELSE 0);
        FOR i:= 1 STEP 1 UNTIL cover_length DO outchar(' ');
      END;
      answer:- NOTEXT;
    END;
    IF answer.length > temp_answer.length AND
    NOT (NOT echoenabled AND got_movechar
    AND temp_answer.length = 1) THEN
    BEGIN
      move_the_cursor_to(h+header.length+1+temp_answer.
      length, v);
      cover_length:= answer.length;
      FOR i:= temp_answer.length+1 STEP 1 UNTIL
      cover_length DO outchar(' ');
    END;
    IF (IF temp_answer == NOTEXT THEN FALSE
    ELSE temp_answer.sub(1,1) = "^") THEN
    BEGIN
      TEXT searched; REF(field) test_field;
      screen_answer(answer);
      searched:- temp_answer.sub(2,temp_answer.length-1);
      test_field:- first_field;
      WHILE test_field =/= NONE DO
      BEGIN
        IF test_field.header.length >= searched.length
        THEN
        BEGIN
          IF test_field.header.sub(1,
          searched.length) = searched THEN
          BEGIN
            IF test_field =/= THIS field THEN
            BEGIN
              IF main_field == NONE THEN main_field:-
              THIS field;
              resume(test_field);
            END;
            GOTO get_answer;
          END;
        END;
        test_field:- test_field.next;
      END;
      error("No such header.");
    END;
    IF NOT echoenabled THEN
    BEGIN
      IF got_movechar THEN
      BEGIN
        INTEGER goalline, goalorder;
        BOOLEAN modified_goal;
        REF (field) test_field, back_field;
        IF movechar = home THEN
        BEGIN goalline:= 0; goalorder:= 1;
        END ELSE IF movechar = left THEN
        BEGIN goalline:= v; goalorder:= orderinline-1;
          IF goalorder < 1 THEN goalorder:= 1;
        END ELSE IF movechar = right THEN
        BEGIN goalline:= v; goalorder:= orderinline+1;
        END ELSE IF movechar = up THEN
        BEGIN goalline:= v-1; goalorder:= orderinline;
        END ELSE IF movechar = down THEN
        BEGIN goalline:= v+1; goalorder:= orderinline;
        END;
        test_field:- first_field;
        WHILE test_field =/= NONE DO
        BEGIN
          tryagain: IF test_field.v = goalline AND
          test_field.orderinline =
          goalorder THEN GOTO found;
          IF test_field.v > goalline THEN
          BEGIN
            IF back_field =/= NONE THEN
            BEGIN
              IF movechar = up AND NOT modified_goal THEN
              BEGIN
                modified_goal:= TRUE;
                goalline:= back_field.v;
                test_field:-first_field;
                GOTO tryagain;
              END ELSE IF movechar = down THEN
              BEGIN
                IF test_field.v-back_field.v>1 THEN
                goalline:=
                goalline+test_field.v-back_field.v-1;
                GOTO tryagain;
              END;
            END;
            GOTO backfound;
          END;
          back_field:- test_field;
          test_field:- test_field.next;
        END;
        IF movechar = down AND NOT modified_goal THEN
        BEGIN
          modified_goal:= TRUE;
          goalline:= goalline-1;
          test_field:- first_field;
          GOTO tryagain;
        END;
        backfound: IF back_field =/= NONE
        THEN test_field:- back_field;
        found: IF test_field =/= THIS field THEN
        BEGIN
          IF main_field == NONE THEN main_field:-
          THIS field;
          resume(test_field);
        END;
        GOTO get_answer;
      END;
    END;
    answer:- temp_answer;
    INNER; IF main_field == NONE THEN detach ELSE
    BEGIN temp_field:- main_field; main_field:- NONE;
      IF temp_field =/= THIS field AND
      temp_field.answer == NOTEXT THEN
      resume(temp_field) ELSE detach;
    END;
    GOTO get_answer;
  END of field;

  field CLASS intfield(min,max,rangerror);
  VALUE rangerror; INTEGER min, max; TEXT rangerror;
  BEGIN
    INTEGER intvalue;
    answer.setpos(1);
    IF checkint(answer) >= 1 AND NOT answer.more THEN
    BEGIN
      answer.setpos(1); intvalue:= answer.getint;
      IF intvalue < min OR intvalue > max THEN
      error(rangerror);
    END ELSE error("Integer input was expected.");
  END;

  field CLASS realfield(min,max,rangerror);
  VALUE rangerror; REAL min, max; TEXT rangerror;
  BEGIN
    REAL realvalue;
    answer.setpos(1);
    IF checkreal(answer) >= 1 AND NOT answer.more THEN
    BEGIN
      answer.setpos(1); realvalue:= answer.getreal;
      IF realvalue < min OR realvalue > max THEN
      error(rangerror);
    END ELSE error("Integer input was expected.");
  END;

  field CLASS choicefield(nonemessage);
  VALUE nonemessage; TEXT nonemessage;
  BEGIN
    CLASS choice(choicetext);
    VALUE choicetext; TEXT choicetext;
    BEGIN
      REF (choice) nextchoice;
      upcase(choicetext);
      IF lastchoice =/= NONE THEN
      lastchoice.nextchoice:- THIS choice ELSE
      firstchoice:- THIS choice;
      lastchoice:- THIS choice;
    END;
    REF (choice) firstchoice, lastchoice, tempchoice;
    REF (choice) foundchoice;
    foundchoice:- NONE;
    upcase(answer);
    IF answer =/= NOTEXT THEN
    BEGIN
      tempchoice:- firstchoice;
      WHILE tempchoice =/= NONE DO
      BEGIN
        INSPECT tempchoice DO
        IF answer.length <= choicetext.length THEN
        BEGIN
          IF choicetext.sub(1,answer.length) = answer THEN
          BEGIN
            IF answer.length EQ choicetext.length THEN
            GOTO good;
            IF foundchoice =/= NONE THEN
            BEGIN
              error("Ambiguous entry, give more characters.");
              GOTO good;
            END;
            foundchoice:- tempchoice;
          END;
        END;
        tempchoice:- tempchoice.nextchoice;
      END;
    END;
    IF foundchoice == NONE THEN error(nonemessage)
    ELSE change_answer(foundchoice.choicetext);
    good:
  END of choicefield;

  field CLASS alphafield;
  BEGIN
    answer.setpos(1);
    WHILE answer.more DO
    BEGIN
      c:= answer.getchar;
      IF NOT letter(c) AND c NE ' ' THEN
      error("Only letters accepted in answer.");
    END;
  END of alphafield;
  line:= -1;
END of form;