home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug005.arc / WINDOWS.C < prev    next >
Text File  |  1979-12-31  |  13KB  |  339 lines

  1. /*        WINDOWS ROUTINES        Dave Nowlan
  2. .po0
  3.                                May 85    */
  4. struct     Window    Screen;
  5. /* set up a structure to hold the picture of the real screen */
  6. /*---------------------------------------------------------------------------*/
  7. Wcursor(window)        /* routine to put cursor at current position */
  8. struct    Window    *window;
  9. /* regardless of what the program might think, the operating system thinks 
  10. that the screen is 80 * 25. If the facts are different we must fiddle the 
  11. address so that it works. If the cursor would be off the real screen leave
  12. it at home and BEEP. Call Wpoke with a null to get the address relative to 
  13. the start of screen RAM */
  14. {    int     a,x,y;
  15.     a = Wpoke(window,'\0');        /* returns -1 if off the screen */
  16.     if (a!=-1)
  17.     {    y = (a / 80) + 32;    x = (a % 80) + 32;    }
  18.     else
  19.     {    y=32;    x=32;    putchar(7);    }
  20.     putchar(ESC);    putchar('=');
  21.     putchar(y);    putchar(x);
  22.     return;
  23. }
  24. /*---------------------------------------------------------------------------*/
  25. Wdisplay(window)
  26. struct    Window    *window;
  27. /* this routine is really only for testing but can be used when you want. 
  28. Note that it does not use the windows but splatters the message where CP/M
  29. thinks the cursor should be */
  30. {    printf("\nScreen\n");
  31.     printf("displacement %d %d ", Screen.Column, Screen.Row);
  32.     printf("width %d  depth %d ", Screen.Width, Screen.Depth);
  33.     printf("X Y position %d %d ", Screen.CursX, Screen.CursY);
  34.     printf("fore/back is %d %d ", Screen.Fore, Screen.Back);
  35.     printf("\nwindow\n");
  36.     printf("displacement %d %d ", window->Column, window->Row);
  37.     printf("width %d  depth %d ", window->Width, window->Depth);
  38.     printf("X Y position %d %d ", window->CursX, window->CursY);
  39.     printf("fore/back is %d %d \n", window->Fore, window->Back);
  40.     return;
  41. }
  42. /*--------------------------------------------------------------------------*/
  43. Wfold(window)
  44. struct    Window    *window;    /* defines position, size and colour of it */
  45. {
  46. /* this routine `folds' the CursX,Y coordinates into the window. It does not 
  47. scroll but wraps around within the window width and depth until it fits. If 
  48. the window does not exist it gives up in disgust. It assumes that the current
  49. location is not far outside the window. The new position is returned by 
  50. updating CursX,Y in the window */
  51.     if ((window->Width < 1) || (window->Depth < 1))
  52.     {    printf("Window is %d wide and %d deep", 
  53.             window->Width, window->Depth);
  54.         exit();
  55.     }
  56. /* if x is off right hand end of window drop down a line */
  57.     while (window->CursX >= window->Width)
  58.     {    window->CursX -= window->Width;        
  59.         window->CursY++;    
  60.     }
  61. /* if x is off left hand end of window go up one line */
  62.     while (window->CursX < 0)
  63.     {    window->CursX += window->Width; 
  64.         window->CursY--;    
  65.     }    
  66. /* if y below window wrap round to the top */
  67.     while (window->CursY >= window->Depth)
  68.     {    window->CursY -= window->Depth;        }
  69. /* if y above window wrap round to the bottom */
  70.     while (window->CursY < 0)
  71.     {    window->CursY += window->Depth;        }
  72.     return;
  73. }
  74. /*---------------------------------------------------------------------------*/
  75. Wgetchar(window)        /* gets a character from the window */
  76. struct    Window     *window;     /* position, size and colour of it */
  77. {    char    c;        /* to hold the character from the keyboard */
  78. /* find current position in the window and put cursor there if on screen */
  79.     Wfold(window);
  80.     Wpoke(window,160);
  81. /* get next character using MCHINW in the ROM. If it is a null ignore it */
  82.     do {    c = calla(0xe006);    }    
  83.         while (c==0);
  84.     Wpoke(window,' ');    /* clear the cursor and return the character */
  85.     return(c);
  86. }
  87. /*---------------------------------------------------------------------------*/
  88. Wgets(window,option)        /* gets a string from the window */
  89. struct    Window    *window;    /* position, size and colour of it */
  90. int    option;            /* whether to accept control characters */
  91. {    char    c,string[128];    /* to hold the gotten string */
  92.     int    i;
  93. /* put cursor in the right place and then get characters until a return.
  94. If second parameter is TRUE, include all control characters else don't. The 
  95. only control characters actioned by this routine are
  96.     BACKSPACE (^h) to cancel one character
  97.     CANCEL (^x) to cancel everything so far 
  98.     RETURN (^m) to mark end of input */
  99.     i=0;
  100.     do    /* until RETURN or string full */
  101.     {    c=Wgetchar(window);
  102. /* if a backspace go back one spot unless still at initial position */
  103.         if (c == Left)
  104.         {    if (i)
  105.             {    window->CursX--;    i--;    }
  106.             continue;    
  107.         }
  108. /* if a cancel (^X) then scrap all input so far by moving cursor back */
  109.         if (c == Cancel)
  110.         {    if (i)
  111.             {    window->CursX -= i;    i=0;    }
  112.             continue;
  113.         }
  114. /* if a control character and not wanted then Beep and go round again */
  115.         if (c < ' ' && option == FALSE)
  116.         {    if (c != Return)
  117.                 putchar(7);    
  118.             continue;    
  119.         }
  120. /* if wanted add to string and write to the screen */
  121.         string[i] = c;
  122.         Wpoke(window,c);
  123.         window->CursX++;
  124.         i++;
  125.     }
  126.     while (i < 128 && c != Return);
  127. /* at end add the final null and return address of the string */
  128.     string[i] = '\0';
  129.     return(&string[0]);
  130. }    
  131. /*---------------------------------------------------------------------------*/
  132. Winitial(colour,red,green,blue)
  133. int    colour;        /* FALSE if no colours to be processed at all */
  134. int     red,green,blue;    /* FALSE if that colour is half intensity else full */
  135. {
  136. /* this routine must be called before any other window routine. It uses a 
  137. global Window structure called Screen to define the real screen. First define 
  138. the origin of the real screen as X,Y displacements from the start of screen 
  139. RAM. Usually this is 0,0 but can be changed - don't blame me if you do. All 
  140. other windows are relative to the origin as defined here */
  141.     Screen.Column = 0;
  142.     Screen.Row = 0;
  143. /* now define the shape of the screen as seen by the user. By default this is
  144. 80 by 25 but may have be changed eg if E01E is called for a 64 by 16 screen */
  145.     Screen.Width = 80;
  146.     Screen.Depth = 25;
  147. /* the cursor position is irrelevant as the Screen structure should not be 
  148. used as a window. If you do, I take no responsibility for the results!!!! */
  149.     Screen.CursX = 0;
  150.     Screen.CursY = 0;
  151. /* the foreground colour field is used to tell Wpoke whether to access the
  152. possibly non-existent colour RAM. The first parameter to this routine should 
  153. be FALSE unless you have a colour BEE !!!!!!!! */
  154.     Screen.Fore = colour;
  155. /* the next three parameters define whether the three colour guns are set to 
  156. full (not FALSE) or half intensity (FALSE) for the background colours for the 
  157. entire screen. Refer to your manual. Try FALSE FALSE FALSE for starters */
  158.     Screen.Back = 0;    /* start with all three colours at half */
  159.     if (colour)        /* if (and only if) colour was asked for */
  160.     {    if (red)    /* turn on full red ie bit 1 */
  161.             Screen.Back |= 2;
  162.         if (green)    /* turn on full green ie bit 2 */
  163.             Screen.Back |= 4;
  164.         if (blue)    /* turn on full blue ie bit 3 */
  165.             Screen.Back |= 8;
  166.     }
  167. /* finally leave CP/M thinking that cursor is at home */
  168.     Wcursor(Screen);
  169.     return;
  170. }
  171. /*---------------------------------------------------------------------------*/
  172. Wpoke(window,it)
  173. struct    Window    *window;    /* defines position, size and colour of it */
  174. char    it;            /* what to poke into the window */
  175. {    int    colour,spot,x,y;
  176. /* first of all see if the spot is within the logical screen. Add the position 
  177. within the window to the origin of the window and then to the origin of the
  178. screen. If not within the logical screen return FALSE. Note that this allows 
  179. windows to be scrolled - if you refresh the contents of the windows!!!!!!! */
  180.     x = window->CursX + window->Column + Screen.Column;
  181.     if (x < 0 || x >= Screen.Width)
  182.         return(-1);
  183.     y = window->CursY + window->Row + Screen.Row;
  184.     if (y < 0 || y >= Screen.Depth)
  185.         return(-1);
  186. /* now see if the spot is within the real screen RAM ie from 0xf000 to 0xf7ff.
  187. If it isn't, it can't be displayed so return -1. If it is, calculate real 
  188. address to be poked */
  189.     spot = (y * Screen.Width) + x;
  190.     if (spot & 0xf800)
  191.         return(-1);
  192. /* now check to see if called with a null. If so return from here */
  193.     if (it == 0)
  194.         return(spot);
  195. /* if colour was selected in Winitial build colour byte and poke it in */
  196.     if (Screen.Fore)            /* if colour selected */
  197.     {    colour = (window->Back << 5) + window->Fore;
  198.         outp (8,(Screen.Back | 64));    /* select colour RAM */
  199.         poke ((spot | 0xf800), colour);    /* poke in the colour */
  200.         outp (8,Screen.Back);        /* go back to PCG RAM */
  201.     }
  202. /* finally poke in the character advised */
  203.     poke ((spot | 0xf000),it);    
  204.     return(spot);
  205. }
  206. /*---------------------------------------------------------------------------*/
  207. Wputchar(window,it)
  208. struct    Window    *window;    /* defines position, size and colour of it */
  209. char    it;            /* the character of the moment */
  210. {    int    x,y;
  211.  /* first of all sort out all the control characters which don't need the 
  212. folded address in the window to be calculated. Maybe a bell */
  213.     if (it == Bell)
  214.     {    putchar(7);    return;        }
  215. /* move cursor one spot in the appropiate direction */
  216.     if (it == Left)
  217.     {    window->CursX--;    return;        }
  218.     if (it == Right)
  219.     {     window->CursX++;    return;        }
  220.     if (it == Up)
  221.     {    window->CursY--;    return;        }
  222.     if (it == Down)
  223.     {    window->CursY++;    return;        }
  224. /* at return move cursor to start of next line; do not space fill rest of 
  225. the current line as this can be by using Clrline */
  226.     if (it == Return)
  227.     {    window->CursX=0;
  228.         window->CursY++;
  229.         return;    
  230.     }
  231. /* at home move cursor to top left corner of window */
  232.     if (it == Home)
  233.     {    window->CursX=0;     
  234.         window->CursY=0;    
  235.         return;    
  236.     }
  237. /* if a clear screen, space out the window from bottom right to top left. 
  238. There is no good reason for going this way except that it leaves the cursor
  239. position correctly at the origin of the window */
  240.     if (it == Clear)
  241.     {    window->CursY = window->Depth;
  242.         while (window->CursY)
  243.         {    window->CursY--;
  244.             window->CursX = window->Width;
  245.             while (window->CursX)
  246.             {    window->CursX--;    
  247.                 Wpoke(window,' ');  
  248.             }
  249.         }
  250.         return;
  251.     }
  252. /* all the following codes need the correct position in the window to be 
  253. calculated so call Wfold to do it */
  254.     Wfold(window);
  255. /* if a delete, write a space to current position and then move cursor back 
  256. one position */
  257.     if (it == Delete)
  258.     {    Wpoke(window,' ');    
  259.         window->CursX--;    
  260.         return;    
  261.     }
  262. /* if not a control character ie at least 0x20 then display it */
  263.     if (it & 0xe0)
  264.     {    Wpoke(window,it);    
  265.         window->CursX++;    
  266.         return;    
  267.     }
  268. /* Tab means space fill to the next mutiple of 8 characters from the start 
  269. of the window or the end of the current line if that comes first. Unless the
  270. cursor is already at the end of the line always give at least one space */
  271.     if (it == Tab)    
  272.     {    if (window->CursX >= window->Width)
  273.         {    return;        }
  274.         do                
  275.         {    Wpoke(window,' ');    
  276.             window->CursX++;    
  277.         }
  278.         while     ((window->CursX < window->Width)    
  279.             && (window->CursX & 7));        
  280.         return;
  281.     }
  282. /* if a clear current line or clear rest of page, space fill the rest of 
  283. the current line or page but leave cursor where it is */
  284.     if (it == Clrline || it == Clrpage)
  285.     {    x=window->CursX;    /* save current CursX */
  286.         y=window->CursY;    /* save current CursY */
  287.     /* space fill rest of cuurent line */
  288.         while (window->CursX < window->Width)
  289.         {    Wpoke(window,' ');    
  290.             window->CursX++;    
  291.         }
  292.     /* if clear page space fill the rest of the lines in the window */
  293.         if (it == Clrpage)
  294.         {    window->CursX=0;    
  295.             window->CursY++;
  296.             while (window->CursY < window->Depth)
  297.             {    while (window->CursX < window->Width)
  298.                 {    Wpoke(window,' ');
  299.                     window->CursX++;    
  300.                 }
  301.                 window->CursX=0;    
  302.                 window->CursY++;
  303.             }
  304.         }
  305.         window->CursX=x;    /* restore saved CursX */
  306.         window->CursY=y;    /* restore saved CursY */
  307.         return;
  308.     }
  309. /* no other character updates the screen */
  310.     return;
  311. }
  312. /*---------------------------------------------------------------------------*/
  313. Wputs(window,string)
  314. struct    Window    *window;    /* defines position, size and colour of it */
  315. char    string[];        /* the string to be processed */
  316. {    char    it;
  317.     int     i;
  318. /* from the start of the string, work through it one character at a time 
  319. until you get to the terminating null */
  320.     i = 0;    
  321.     while ((it = string[i]))    
  322.     {    Wputchar(window,it);    i++;    }
  323. /* call Wfold to get final cursor position in window right */
  324.     Wfold(window);
  325.     return;
  326. }
  327. /*---------------------------------------------------------------------------*/
  328. Wsize(width,depth)        /* routine to change real screen size */
  329. {    if (width < 1 || depth < 1)
  330.         {    printf("Wsize invalid screen width %d or depth %d", 
  331.                width, depth);
  332.         exit();
  333.     }
  334.     Screen.Width=width;
  335.     Screen.Depth=depth;
  336.     return(TRUE);
  337. }
  338. /*---------------------------------------------------------------------------*/
  339.