home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff330.lzh / Vt100 / Src.lzh / Src / window.c < prev    next >
C/C++ Source or Header  |  1990-03-01  |  21KB  |  767 lines

  1. static char rcsid[] = "$RCSfile: window.c,v $ $Revision: 1.5 $";
  2.  
  3. /****************************************************
  4.  * vt100 emulator - window/keyboard support
  5.  *        :ts=8
  6.  *
  7.  * $Log:    window.c,v $
  8.  * Revision 1.5  90/01/23  20:17:11  acs
  9.  * 1) Machine would lock up due to req() "missing" some events.  Thanks
  10.  *    to Patrick Horgan (phorgan@cup.portal.com) for all his work on
  11.  *    this one!
  12.  * 2) Remove some extraneous white-space for appearances sake.
  13.  * 
  14.  * Revision 1.4  89/12/18  20:47:12  acs
  15.  * emit() no longer needs to strip parity...the main loop in vt100.c
  16.  * takes care of it now.
  17.  * 
  18.  * Revision 1.3  89/11/02  10:14:24  acs
  19.  * Support for new STRIP command to strip parity from data destined for
  20.  * display.
  21.  * 
  22.  * Revision 1.2  89/11/01  20:32:28  acs
  23.  * 1) Correct interchanged use of Xsize and Ysize.  Thanks to Sean Hogan
  24.  *    (sean2@garfield.mun.ca).
  25.  * 2) Add RCS id and change log.
  26.  * 
  27.  *    v2.9 ACS - See change summary.
  28.  *    v2.7 870825 ACS - Provide an info/status window rather than using
  29.  *              req().  Better error handling.
  30.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  31.  *    v2.5 870214 DBW - more additions (see readme file)
  32.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  33.  *    v2.3 861101 DBW - minor bug fixes
  34.  *    v2.2 861012 DBW - more of the same
  35.  *    v2.1 860915 DBW - new features (see README)
  36.  *         860823 DBW - Integrated and rewrote lots of code
  37.  *    v2.0 860809 DBW - Major rewrite
  38.  *    v1.1 860720 DBW    - Switches, 80 cols, colors, bug fixes
  39.  *    v1.0 860712 DBW    - First version released
  40.  *
  41.  ****************************************************/
  42.  
  43. #include "vt100.h"
  44.  
  45. static char *infkey[] = {    /* F-keys resulting from RawKeyConvert() */
  46.     "0~",  "1~",  "2~",  "3~",  "4~",  "5~",  "6~",  "7~",  "8~",  "9~",
  47.     "10~", "11~", "12~", "13~", "14~", "15~", "16~", "17~", "18~", "19~",
  48.     NULL};
  49.  
  50. /* Cursor keys resulting from RawKeyConvert() and their output values */
  51. static struct {
  52.     char *in;        /* in sequence */
  53.     char *out_curapp;    /* out sequence in p_curapp */
  54.     char *out;        /* out sequence !in p_curapp */
  55. } ckeys[] = {
  56.     "A",    "OA",    "[A",
  57.     "T",    "OA",    "[A",
  58.     "B",    "OB",    "[B",
  59.     "S",    "OB",    "[B",
  60.     "C",    "OC",    "[C",
  61.     " A~",    "OC",    "[C",
  62.     "D",    "OD",    "[D",
  63.     " @~",    "OD",    "[D",
  64.     NULL,    NULL,    NULL    };
  65.  
  66. /*   Numeric keypad for A2000 and A500 have keys that the A1000 doesn't have.
  67. ** Use them for the VT100 F-keys. */
  68. static char npfkey[] = {
  69.     '(', 'P', ')', 'Q', '*', 'R', '/', 'S', 0, 0};
  70.  
  71. /* Numeric keypad return values excluding HELP, '-' and ENTER */
  72. static char keypad[] = {
  73.     'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '\0'};
  74. /* Numeric keypad return values for HELP, - and ENTER */
  75. static char speckeypad[] = {
  76.     '-',    'l',    '-',
  77.     '.',    'n',    '.',
  78.     '\015',    'M',    '\015',
  79.     '\0',    '\0',    '\0'    };
  80.  
  81. /* For InfoMsg...may be changed by a NEWSIZE msg in vt100.c */
  82. int reqminx,    /* Min value for x in reqwindow (pixels) */
  83.     reqmaxx,    /* Max value for x in reqwindow (pixels) */
  84.     reqmaxlen,    /* Max # chars in reqwindow */
  85.     reqminy,    /* Min value for y in reqwindow (scan lines) */    
  86.     reqmaxy,    /* Max value for y in reqwindow (scan lines) */
  87.     reqfudge;    /* Clear space between border and start of 1st char */
  88. int reqy;    /* Current pixel location in reqwindow */
  89.  
  90. void ReqNewSize(), OpenReqWindow();
  91.  
  92. /***************************************************
  93.  *  function to swap the use of backspace and delete
  94.  ***************************************************/
  95.  
  96. void swap_bs_del()
  97. {
  98.     if (p_bs_del)   p_bs_del = 0;
  99.     else        p_bs_del = 1;
  100. }
  101.  
  102. /*************************************************
  103.  *  function to get file name (via a requestor)
  104.  *************************************************/
  105. void req(prmpt,name,getinp)
  106. char *prmpt,*name;
  107. int  getinp;
  108.     {
  109.     ULONG class;
  110. #if MANX
  111.     USHORT RemoveGadget();
  112. #endif /* MANX */
  113.     int  lprmpt, lname, done;
  114.     struct IntuiMessage *Msg;
  115.  
  116.     if(reqwinup == 0)
  117.     OpenReqWindow();
  118.     
  119.     if(!getinp) {
  120.         InfoMsg2Line(prmpt, name);
  121.         return;
  122.     }
  123.  
  124.     lprmpt = strlen(prmpt);
  125.     lname = strlen(name);
  126.  
  127.     /* Don't use strings longer than what we've provided space for. */
  128.     if(lprmpt > (MAXGADSTR-1)) {
  129.     emits("Prompt too long - truncated.\n");
  130.     lprmpt = MAXGADSTR-1;
  131.     }
  132.     if(lname > (MAXGADSTR-1)) {
  133.     emits("Name too long - truncated.\n");
  134.     lname = MAXGADSTR-1;
  135.     }
  136.  
  137.     if (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  138.     class = Msg->Class;
  139.     ReplyMsg((struct Message *)Msg);
  140.     if(class == REQCLEAR)
  141.         numreqs = 0;
  142.     if(class == NEWSIZE)
  143.         ReqNewSize(reqwindow->Height, reqwindow->Width);
  144.     }
  145.  
  146.     /* Make sure the prompt gets updated */
  147.     if (numreqs == 1 && strcmp(Prompt,prmpt) != 0) {
  148.     EndRequest(&myrequest,reqwindow);
  149.     done = 0;
  150.     do {
  151.         Wait(1L << reqwindow->UserPort->mp_SigBit);
  152.         while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  153.             class = Msg->Class;
  154.             ReplyMsg((struct Message *)Msg);
  155.             if(class == NEWSIZE)
  156.                 ReqNewSize(reqwindow->Height, reqwindow->Width);
  157.             if(class == REQCLEAR)
  158.                 done = 1;
  159.         }
  160.     } while(!done);
  161.     numreqs = 0;
  162.     }
  163.  
  164.     /* copy in a prompt and a default */
  165.     strncpy(Prompt,prmpt,lprmpt); Prompt[lprmpt] = '\0';
  166.     strncpy(InpBuf,name,lname); InpBuf[lname] = '\0';
  167.     mystrinfo.BufferPos = lname;
  168.  
  169.     if (numreqs == 1) {        /* If there is a requester... reuse it */
  170.         RefreshGadgets(&mystrgad, reqwindow, &myrequest);
  171.         Delay(2L);
  172.     }
  173.     else {            /* otherwise create it */
  174.     while(numreqs != 1) {
  175.             if (Request(&myrequest, reqwindow) == 0) {
  176.         emits("ERROR - CAN'T CREATE REQUESTOR FOR:\n");
  177.         emits(Prompt); emit('\n'); emits(InpBuf); emit('\n');
  178.         return;
  179.         }
  180.         else numreqs = 1;
  181.  
  182.         done = 0;
  183.         do {
  184.         Wait(1L << reqwindow->UserPort->mp_SigBit);
  185.         while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  186.             class = Msg->Class;
  187.             ReplyMsg((struct Message *)Msg);
  188.             if(class == REQCLEAR)
  189.             numreqs = 0;
  190.             if(class == NEWSIZE)
  191.             ReqNewSize(reqwindow->Height, reqwindow->Width);
  192.             if(class == REQSET)
  193.             done = 1;
  194.         }
  195.         } while(!done);
  196.     } /* end while numreqs != 0 */
  197.     } /* end else */
  198.  
  199.     /* if we don't want input, we're done */
  200.     if (getinp == 0 || numreqs == 0) return;
  201.  
  202.     if((reqwindow->Flags & WINDOWACTIVE) != WINDOWACTIVE) {
  203.         WindowToFront(reqwindow);
  204.     ActivateWindow(reqwindow);
  205.     done = 0;
  206.     do {
  207.         Wait(1L << reqwindow->UserPort->mp_SigBit);
  208.         while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  209.         class = Msg->Class;
  210.         ReplyMsg((struct Message *)Msg);
  211.         if(class == NEWSIZE)
  212.             ReqNewSize(reqwindow->Height, reqwindow->Width);
  213.         if(class == ACTIVEWINDOW)
  214.             done = 1;
  215.         }
  216.     } while(!done);
  217.     }
  218.     
  219.     /* here is where we pre-select the gadget   */
  220.     if (!ActivateGadget(&mystrgad,reqwindow,&myrequest)) {
  221.  
  222.     /* wait for his/her hands to get off the keyboard (Amiga-key) */
  223.     Delay(20L);
  224.     while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  225.         ReplyMsg((struct Message *)Msg);
  226.         if(class == NEWSIZE)
  227.         ReqNewSize(reqwindow->Height, reqwindow->Width);
  228.     }
  229.  
  230.     /* try once more before giving up... */
  231.     ActivateGadget(&mystrgad,reqwindow,&myrequest);
  232.     }
  233.  
  234.     /* wait for input to show up */
  235.     while (1) {
  236.     if ((NewMessage = (struct IntuiMessage *)
  237.         GetMsg(reqwindow->UserPort)) == FALSE) {
  238.         Wait(1L<<reqwindow->UserPort->mp_SigBit);
  239.         continue;
  240.     }
  241.     class = NewMessage->Class;
  242.     ReplyMsg((struct Message *)NewMessage);
  243.  
  244.     /* the requestor got terminated... yea!! */
  245.     if (class == REQCLEAR) break;
  246.  
  247.     if(class == NEWSIZE)
  248.         ReqNewSize(reqwindow->Height, reqwindow->Width);
  249.         
  250.     }
  251.  
  252.     /* all done, so return the result */
  253.     numreqs = 0;
  254.     strcpy(name,InpBuf);
  255.     if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
  256.     ActivateWindow(mywindow);
  257.     }
  258.  
  259. /*************************************************
  260. *  function to print a string
  261. *************************************************/
  262. void emits(string)
  263. char string[];
  264.     {
  265.     int i;
  266.     char c;
  267.  
  268.     i=0;
  269.     while (string[i] != 0)
  270.     {
  271.     c=string[i];
  272.     if (c == 10) emit(13);
  273.     emit(c);
  274.     i += 1;
  275.     }
  276.     }
  277.  
  278. /*************************************************
  279. *  function to output ascii chars to window
  280. *************************************************/
  281. void emit(c)
  282. char c;
  283.     {
  284.     static char wrap_flag = 0;    /* are we at column 80? */
  285.  
  286.     switch( c )
  287.     {
  288.     case '\t':
  289.     x += (Xsize * 8) - ((x-MINX) % (Xsize * 8));
  290.     break;
  291.  
  292.     case 10:  /* lf */
  293.     doindex('D');
  294.     break;
  295.  
  296.     case 13:  /* cr */
  297.     x = MINX;
  298.     break;
  299.  
  300.     case 8:   /* backspace */
  301.     x -= Xsize;
  302.     if (x < MINX) x = MINX;
  303.     break;
  304.  
  305.     case 12:     /* page */
  306.     x = MINX;
  307.     y = MINY;
  308.     SetAPen(mywindow->RPort,0L);
  309.     RectFill(mywindow->RPort,(long)MINX,
  310.         (long)(MINY-BaseLine),(long)(MAXX+(Xsize-1)),(long)(MAXY+1));
  311.     SetAPen(mywindow->RPort,1L);
  312.     break;
  313.  
  314.     case 7:     /* bell */
  315.     cmd_beep(0L);
  316.     break;
  317.  
  318.     default:
  319.     if (c < ' ' || c > '~') break;
  320.     if (p_wrap && wrap_flag && x >= MAXX) {
  321.         x = MINX;
  322.         doindex('D');
  323.         if (y > MAXY) {
  324.         y = MAXY;
  325.         ScrollRaster(mywindow->RPort,0L,(long)Ysize,(long)MINX,
  326.             (long)(MINY-(BaseLine+1)),(long)(MAXX+(Xsize - 1)),
  327.             (long)(MAXY+1));
  328.         }
  329.         }
  330.     Move(mywindow->RPort,(long)x,(long)y);
  331.  
  332.     if (curmode&FSF_BOLD) {
  333.         if (p_depth > 1) {
  334.         SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
  335.         SetSoftStyle(mywindow->RPort,(long)curmode,253L);
  336.         }
  337.         else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
  338.         }
  339.     else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
  340.  
  341.     if (curmode&FSF_REVERSE) {
  342.         SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
  343.         Text(mywindow->RPort,&c,1L);
  344.         SetDrMd(mywindow->RPort,(long)JAM2);
  345.         }
  346.     else Text(mywindow->RPort,&c,1L);
  347.  
  348.     if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
  349.     x += Xsize;
  350.     } /* end of switch */
  351.  
  352.     if (y > MAXY) {
  353.     y = MAXY;
  354.     x = MINX;
  355.     ScrollRaster(mywindow->RPort,0L,(long)Ysize,(long)MINX,
  356.         (long)(MINY-(BaseLine+1)),(long)(MAXX+(Xsize - 1)),
  357.         (long)(MAXY+1));
  358.     }
  359.     if (x > MAXX) {
  360.     wrap_flag = 1;
  361.     x = MAXX;
  362.     }
  363.     else wrap_flag = 0;
  364.     }
  365.  
  366. /*************************************************
  367. *  function to output ascii chars to window (batched)
  368. *************************************************/
  369. void emitbatch(la,lookahead)
  370. int la;
  371. char *lookahead;
  372.     {
  373.     int i;
  374.  
  375.     Move(mywindow->RPort,(long)x,(long)y);
  376.     i = x / Xsize;
  377.     if (i+la >= maxcol) {
  378.     if (p_wrap == 0) la = maxcol - i;
  379.     else {
  380.         lookahead[la] = 0;
  381.         emits(lookahead);
  382.         return;
  383.         }
  384.     }
  385.     if (curmode&FSF_BOLD) {
  386.     if (p_depth > 1) {
  387.         SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
  388.         SetSoftStyle(mywindow->RPort,(long)curmode,253L);
  389.         }
  390.     else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
  391.     }
  392.     else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
  393.  
  394.     if (curmode&FSF_REVERSE) {
  395.     SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
  396.     Text(mywindow->RPort,lookahead,(long)la);
  397.     SetDrMd(mywindow->RPort,(long)JAM2);
  398.     }
  399.     else Text(mywindow->RPort,lookahead,(long)la);
  400.     if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
  401.     x += (Xsize * la);
  402.     }
  403.  
  404. /******************************
  405. * Manipulate cursor
  406. ******************************/
  407. void cursorflip()
  408.     {
  409.     SetDrMd(mywindow->RPort,(long)COMPLEMENT);
  410.     SetAPen(mywindow->RPort,3L);
  411.     RectFill(mywindow->RPort, (long)(x), (long)(y-BaseLine),
  412.     (long)(x+Xsize-1), (long)(y+(Ysize-BaseLine-1)));
  413.     SetAPen(mywindow->RPort,1L);
  414.     SetDrMd(mywindow->RPort,(long)JAM2);
  415.     }
  416.  
  417. /************************************************
  418. *  function to take raw key data and convert it
  419. *  into ascii chars
  420. **************************************************/
  421. int toasc(retstr, code, qual, maxlen, ia, local)
  422. unsigned char *retstr;
  423. unsigned int code,qual;
  424. int local, maxlen;
  425. APTR ia;
  426. {
  427.     unsigned int ctrl, alt, npad;
  428.     int i,
  429.     cmatch,
  430.     length = 0;    /* length of returned string */
  431.     unsigned char *p = retstr;
  432.     static struct InputEvent ievent = {NULL, IECLASS_RAWKEY,0,0,0};
  433.  
  434.     *p = '\0';
  435.  
  436.     if(code >= 0x5a && code <= 0x5d) {
  437.     /*   Appears to be one of the keys (, ), /, * on the newer keypads.
  438.     ** Convert them to VT100 F1-F4 */
  439.     char t, *convert = "()*/";
  440.  
  441.     t = convert[code - 0x5a];
  442.     for(i = 0; npfkey[i]; i++)
  443.         if(t == npfkey[i]) {
  444.         strcpy(p, "\033O");
  445.         *(p+2) = npfkey[i+1];
  446.         *(p+3) = '\0';
  447.         length = 3;
  448.         break;
  449.         }
  450.     if(*p) {
  451.         sendstring(p);
  452.         return length;
  453.     }
  454.     }
  455.  
  456.     ctrl  = qual & IEQUALIFIER_CONTROL;
  457.     alt      = qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT);
  458.     npad  = qual & IEQUALIFIER_NUMERICPAD;
  459.  
  460.     ievent.ie_Qualifier = qual;
  461.  
  462.     ievent.ie_Code = code;
  463.     /* get previous codes from location pointed to by IAddress
  464.      * this "magic" pointer is valid intil the IntiiMessage is
  465.      * replied
  466.      */
  467.     ievent.ie_position.ie_addr = ia;
  468.     length = RawKeyConvert(&ievent, retstr, (LONG)maxlen, NULL);
  469.     if(length == 0)
  470.     return length;
  471.  
  472.     *(p+length) = '\0';    /* Null terminate the value */
  473.  
  474.     if(npad && length == 1) { /* keypad (excluding HELP key)? */
  475.     register char t = *p;
  476.  
  477.     if(t == '(' || t == ')' || t == '*' || t == '/') {
  478.         for(i = 0; npfkey[i]; i++)
  479.         if(t == npfkey[i]) {
  480.             strcpy(p, "\033O");
  481.             *(p+2) = npfkey[i+1];
  482.             *(p+3) = '\0';
  483.             length = 3;
  484.             break;
  485.         }
  486.     } else if((t >= '0') && (t <= '9')) {
  487.         if(p_keyapp) {
  488.         strcpy(p, "\033O");
  489.         *(p+2) = keypad[t-'0'];
  490.         *(p+3) = '\0';
  491.         length = 3;
  492.         } /* else *p is correct */
  493.     } else for(i = 0; speckeypad[i]; i += 3)
  494.         if(speckeypad[i] == t) {
  495.         if(p_keyapp) {
  496.             strcpy(p, "\033O");
  497.             *(p+2) = speckeypad[i+1];
  498.             length = 3;
  499.         } else
  500.             *p = speckeypad[i+2];
  501.         break;
  502.         }
  503.     } else if((length == 3) && (strcmp(p, "\233?~") == 0)) {
  504.     /* HELP key -- only gen something if in app keypad mode */
  505.     if(p_keyapp) {
  506.         strcpy(p, "\033Om");
  507.         length = 3;
  508.     } else {
  509.         *p = '\0';
  510.         length = 0;
  511.     }
  512.     } else if(length > 1 && retstr[0] == 0x9b) { /* cursor or F-keys? */
  513.     cmatch = 0;
  514.     for(i = 0; ckeys[i].in && !cmatch; i++) {
  515.         if(p_curapp
  516.           && strcmp((p+1), ckeys[i].in) == 0) {
  517.         strcpy((p+1), ckeys[i].out_curapp);
  518.         *p = 0x1b;
  519.         length = strlen(ckeys[i].out_curapp)+1;
  520.         cmatch = 1;
  521.         } else if(strcmp((p+1), ckeys[i].in) == 0) {
  522.         strcpy((p+1), ckeys[i].out);
  523.         *p = 0x1b;
  524.         length = strlen(ckeys[i].out)+1;
  525.         cmatch = 1;
  526.         }
  527.     }
  528.     if(!cmatch) { /* Not cursor, try F-keys */
  529.         for(i = 0; infkey[i]; i++) {
  530.         if(strcmp((p+1), infkey[i]) == 0) {
  531.             if(i > 9)
  532.             strcpy(p, p_F[i-10]);
  533.             else strcpy(p, p_f[i]);
  534.             if(!script_on && *p == p_keyscript) {
  535.             script_start(p+1);
  536.             *p = '\0';
  537.             length = 0;
  538.             }
  539.             length = strlen(p);
  540.             break;
  541.         }
  542.         }
  543.     }
  544.     } else if(ctrl && (length == 1)) {
  545.     /* Control key shortcuts? */
  546.     switch(*p) {
  547.     case '6':
  548.         *p = 30;
  549.         break;
  550.     case '2':
  551.     case ' ': /* @ done by RawKeyConvert? */
  552.         if(!local)
  553.         *p = (alt ? 128 : 0);
  554.         break;
  555.     case '-':
  556.     case '?':
  557.         *p = 31;
  558.         break;
  559.     }
  560.     } else if(alt && !local && length == 1)
  561.     *p |= 0x80; /* Add hi bit if ALT is the only modifier */
  562.     else if(p_bs_del && *p == 8    && length == 1)
  563.     *p = 0x7f;
  564.     else if(p_bs_del && *p == 0x7f && length == 1)
  565.     *p = 8;
  566.  
  567. /*    if (ctrl) {   Are all of these taken care of?
  568.     if (c > '`' && c <= 127) c -= 96;
  569.     else if (c > '@' && c <= '_') c -= 64;
  570.     else if (c == '6') c = 30;
  571.     else if (c == '-' || c == '?') c = 31;
  572.     } */
  573.     for(i = 0; i < length; i++)
  574.     sendchar(*(p++));
  575.     return(length);
  576. }
  577.  
  578. void
  579. KillReq()
  580. {
  581.     struct IntuiMessage *Msg;
  582.     ULONG class;
  583.     
  584.     if(numreqs != 0) {
  585.     EndRequest(&myrequest,reqwindow);
  586.     do {
  587.         Wait(1L << reqwindow->UserPort->mp_SigBit);
  588.         while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  589.             class = Msg->Class;
  590.             ReplyMsg((struct Message *)Msg);
  591.         }
  592.     } while (class != REQCLEAR);
  593.     numreqs = 0;
  594.     }
  595.  
  596.     if(reqwinup) {
  597.         /* First, clear out all pending messages */
  598.     while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  599.         class = Msg->Class;
  600.         ReplyMsg((struct Message *)Msg);
  601.     }
  602.     NewReqWindow.LeftEdge = reqwindow->LeftEdge;    /* Remember ...      */
  603.     NewReqWindow.TopEdge = reqwindow->TopEdge;    /* ...where...      */
  604.     NewReqWindow.Width = reqwindow->Width;        /* ...the user... */
  605.     NewReqWindow.Height = reqwindow->Height;    /* ...put it.      */
  606.     CloseWindow(reqwindow); /* Now we can close the window */
  607.     reqwinup = 0;
  608.     }
  609. }
  610.  
  611. void
  612. InfoMsg2Line(header, msg)
  613. char *header, *msg;
  614. {
  615.     ScrollInfoMsg(1);
  616.     InfoMsgNoScroll(header);
  617.     ScrollInfoMsg(1);
  618.     InfoMsgNoScroll(msg);
  619.     ScrollInfoMsg(1);
  620. }
  621.  
  622. void
  623. InfoMsg1Line(msg)
  624. char *msg;
  625. {
  626.     ScrollInfoMsg(1);
  627.     InfoMsgNoScroll(msg);
  628.     ScrollInfoMsg(1);
  629. }
  630.  
  631. /*   Output the specified data to the "info" window  */
  632. void
  633. ScrollInfoMsg(lines)
  634. int lines;
  635. {
  636. /*  ULONG class;
  637.     struct IntuiMessage *Msg; */
  638.     int pixels = lines * Ysize;
  639.     
  640.     if(!reqwinup)
  641.     OpenReqWindow();
  642.  
  643. /*  if(Msg=(struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  644.     class = Msg->Class;
  645.     ReplyMsg(Msg);
  646.     if(class == NEWSIZE)
  647.         ReqNewSize(reqwindow->Height, reqwindow->Width);
  648.     } */
  649.  
  650.     if ( (reqy += pixels) > reqmaxy) {
  651.     reqy = reqmaxy;
  652.     if(pixels > 0)
  653.         ScrollRaster(reqwindow->RPort, 0L, (LONG)pixels,
  654.         (LONG)reqminx,
  655.         (LONG)reqminy,
  656.         (LONG)(reqmaxx+(Xsize - 1)),
  657.         (LONG)(reqmaxy+(Ysize - 1)));
  658. /* Was:        (LONG)(wp->Width - wp->BorderRight),
  659.         (LONG)(wp->Height - wp->BorderBottom)); */
  660.     }
  661. }
  662.  
  663. void
  664. InfoMsgNoScroll(msg)
  665. char *msg;
  666. {
  667.     LONG msglen = strlen(msg);
  668.  
  669.     ScrollInfoMsg(0);    /* Ensure that the msg will be visible */
  670.  
  671.     if(msglen > reqmaxlen)
  672.     msglen = reqmaxlen;
  673.  
  674.     /*  Position the pen at the baseline of the character (BaseLine scan
  675.     ** lines into it). */
  676.     Move(reqwindow->RPort, (LONG)reqminx, (LONG)(reqy+BaseLine));
  677.     Text(reqwindow->RPort, msg, msglen);
  678. }
  679.  
  680. void
  681. ReqNewSize(height, width)
  682. SHORT height, width;
  683. {
  684.     register struct Window *wp = reqwindow;
  685.     int oldmaxy;
  686.  
  687.     /*   Compute min and max for x and y coordinates.  Note that for y the
  688.     ** value is for the *top* of the character, not the baseline.  Text()
  689.     ** uses a baseline value and so it must be adjusted prior to the call.
  690.     ** When computing the max values, calculate them so that we will have
  691.     ** sufficient room for an entire character. */
  692.     oldmaxy = reqmaxy;
  693.     reqminy = wp->BorderTop + reqfudge;
  694.     reqmaxy = (((height - reqminy - wp->BorderBottom) / Ysize) * Ysize)
  695.         + (reqminy-Ysize);
  696.     reqminx = wp->BorderLeft + reqfudge;
  697.     reqmaxx = (((width - reqminx - wp->BorderRight) / Xsize) * Xsize)
  698.         + (reqminx-Xsize);
  699.     reqmaxlen = (reqmaxx+(Xsize-1)) / Xsize;
  700.     if(oldmaxy > reqmaxy) { /* Clean up the bottom of the window */
  701.     int temp = height - wp->BorderBottom - reqmaxy;
  702.     
  703.     ScrollRaster(wp->RPort, 0L, (LONG)temp,
  704.     (LONG)reqminx,
  705.     (LONG)reqmaxy,
  706.     (LONG)(width - wp->BorderRight),
  707.     (LONG)(height - wp->BorderBottom));
  708.     }
  709. }
  710.  
  711. void
  712. OpenReqWindow()
  713. {
  714.     struct IntuiMessage *Msg;
  715.     ULONG class;
  716.     void ReqNewSize();
  717.     static init = 1;
  718.     
  719.     if(init) {
  720.     myrequest.LeftEdge = (myrequest.LeftEdge * Xsize) + 5;
  721.     myrequest.TopEdge  = (myrequest.TopEdge  * Ysize) + 2;
  722.     myrequest.Width    = (myrequest.Width    * Xsize) + 4;
  723.     myrequest.Height   = (myrequest.Height   * Ysize) + 6;
  724.  
  725.     mydonegad.LeftEdge = (mydonegad.LeftEdge * Xsize) + 2;
  726.     mydonegad.TopEdge  = (mydonegad.TopEdge  * Ysize) + 2;
  727.     mydonegad.Width    = ((strlen(donetxt.IText) + 1) * Xsize) + 0;
  728.     mydonegad.Height   = (mydonegad.Height   * Ysize) + 2;
  729.  
  730.     mystrgad.LeftEdge  = (mystrgad.LeftEdge * Xsize) + 2;
  731.     mystrgad.TopEdge   = (mystrgad.TopEdge  * Ysize) + 4;
  732.     mystrgad.Width     = (mystrgad.Width    * Xsize) + 0;
  733.     mystrgad.Height    = (mystrgad.Height   * Ysize) + 2;
  734.  
  735.     donetxt.LeftEdge   = (donetxt.LeftEdge  * Xsize) + 0;
  736.     donetxt.TopEdge    = (donetxt.TopEdge   * Ysize) + 0;
  737.  
  738.     mystrtxt.LeftEdge  = (mystrtxt.LeftEdge  * Xsize) + 2;
  739.     mystrtxt.TopEdge   = (mystrtxt.TopEdge   * Ysize) + 2;
  740.  
  741.     NewReqWindow.Width    = (NewReqWindow.Width    * Xsize) + 4 + 18;
  742.     NewReqWindow.LeftEdge = (NewReqWindow.LeftEdge * Xsize) + 2;
  743.     NewReqWindow.LeftEdge = NewWindow.LeftEdge + NewWindow.Width
  744.                 - NewReqWindow.Width;
  745.  
  746.     NewReqWindow.TopEdge  = (NewReqWindow.TopEdge  * Ysize) + 7;
  747.     NewReqWindow.Height   = (NewReqWindow.Height   * Ysize) + 11 + 2;
  748.  
  749.     init = 0;
  750.     }
  751.  
  752.     reqwindow = OpenWindow(&NewReqWindow);
  753.     do {
  754.     Wait(1L << reqwindow->UserPort->mp_SigBit);
  755.     while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
  756.         class = Msg->Class;
  757.         ReplyMsg((struct Message *)Msg);
  758.     }
  759.     } while (class != ACTIVEWINDOW);
  760.     reqfudge = 0;    /* Leave 0 pixels/scan lines between border and char */
  761.     ReqNewSize(reqwindow->Height, reqwindow->Width);
  762.     reqy = reqminy;    /* Top of character set by ReqNewSize() */
  763.     reqwinup = 1;
  764.     if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
  765.     ActivateWindow(mywindow);
  766. }
  767.