home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MODEM / UWPC201.ZIP / UW-SRC.ZIP / DISPLAY.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-03  |  20.4 KB  |  781 lines

  1. //-------------------------------------------------------------------------
  2. //
  3. // DISPLAY.CPP - Classes for handling the display of window information.
  4. // 
  5. //  This file is part of UW/PC - a multi-window comms package for the PC.
  6. //  Copyright (C) 1990-1991  Rhys Weatherley
  7. //
  8. //  This program is free software; you can redistribute it and/or modify
  9. //  it under the terms of the GNU General Public License as published by
  10. //  the Free Software Foundation; either version 1, or (at your option)
  11. //  any later version.
  12. //
  13. //  This program is distributed in the hope that it will be useful,
  14. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. //  GNU General Public License for more details.
  17. //
  18. //  You should have received a copy of the GNU General Public License
  19. //  along with this program; if not, write to the Free Software
  20. //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. //
  22. // Revision History:
  23. // ================
  24. //
  25. //  Version  DD/MM/YY  By  Description
  26. //  -------  --------  --  --------------------------------------
  27. //    1.0    21/03/91  RW  Original Version of DISPLAY.CPP
  28. //    1.1    05/05/91  RW  Clean up and start adding Win3 support.
  29. //    1.2    08/06/91  RW  Add support for cut and paste.
  30. //    1.3    28/10/91  RW  Clean up some of the Win3 support.
  31. //
  32. // You may contact the author by:
  33. // =============================
  34. //
  35. //  e-mail: rhys@cs.uq.oz.au
  36. //    mail: Rhys Weatherley
  37. //          5 Horizon Drive
  38. //          Jamboree Heights
  39. //          Queensland 4074
  40. //        Australia
  41. //
  42. //-------------------------------------------------------------------------
  43.  
  44. #include "display.h"        // Declarations for this module.
  45. #include "screen.h"        // Screen display handling routines.
  46. #include "config.h"        // Status positions defined here.
  47. #ifdef    UWPC_WINDOWS
  48. #include "win3.h"        // IDM_* declarations are here.
  49. #endif
  50. #include <mem.h>        // Memory accessing routines.
  51. #include <string.h>        // String handling routines.
  52.  
  53. #pragma    warn    -par
  54.  
  55. #ifdef    UWPC_DOS
  56. #define    CURSOR_OFF()
  57. #define    CURSOR_ON()
  58. #else
  59. #define    CURSOR_OFF()    cursoroff()
  60. #define    CURSOR_ON()    cursoron()
  61. extern    HANDLE    hInstance;
  62. extern    int    UWFontHeight,UWFontWidth;
  63. extern    HFONT    hFont;
  64. #endif
  65.  
  66. void    UWDisplay::show (int X,int Y,unsigned pair)
  67. {
  68.   int offset;
  69.   offset = X + (Y * width);
  70.   screen[offset] = pair;
  71. #ifdef    UWPC_DOS
  72.   if (attop)
  73.     HardwareScreen.draw (X,Y,pair);
  74. #else
  75.   // repaint (X,Y,X,Y);
  76.   HDC hDC;
  77.   unsigned char attr;
  78.   extern COLORREF WindowsAttributes[];
  79.  
  80.   // Initialise the device context to perform drawing within //
  81.   hDC = GetDC (hWnd);
  82.   SetBkMode (hDC,OPAQUE);    // Fill in the background colour always.
  83.   SelectObject (hDC,hFont);    // Get the font to use for characters.
  84.  
  85.   // Set the attribute colours to be used for the character draw //
  86.   attr = pair >> 8;
  87.   if (curson && y == Y && x == X) // Test for the cursor position.
  88.     attr = (attr << 4) | ((attr >> 4) & 0x0F);
  89.   SetBkColor (hDC,WindowsAttributes[(attr >> 4) & 7]);
  90.   SetTextColor (hDC,WindowsAttributes[attr & 7]);
  91.  
  92.   // Draw the character that is to be shown //
  93.   TextOut (hDC,X * UWFontWidth,Y * UWFontHeight,(LPSTR)(&pair),1);
  94.  
  95.   // Clean up the device context information //
  96.   ReleaseDC (hWnd,hDC);
  97. #endif
  98. } // UWDisplay::show //
  99.  
  100. void    UWDisplay::scroll (int x1,int y1,int x2,int y2,int lines,int attribute)
  101. {
  102.   int offset,saveofs,nextofs,x,y,linewid;
  103.   unsigned clearpair;
  104.  
  105.   // Clear or scroll the memory for the screen image //
  106.   clearpair = ' ' | (attribute << 8);
  107.   if (lines == 0)
  108.     {
  109.       // Clear the entire area to be scrolled //
  110.       offset = x1 + (y1 * width);
  111.       for (y = y1;y <= y2;++y)
  112.         {
  113.       saveofs = offset;
  114.           for (x = x1;x <= x2;++x)
  115.         screen[offset++] = clearpair;
  116.       offset = saveofs + width;
  117.     }
  118.     }
  119.    else if (lines > 0)
  120.     {
  121. // #ifdef    DOOBERY
  122.       // Scroll the area up a number of lines //
  123.       offset = x1 + (y1 * width);
  124.       nextofs = offset + width;
  125.       for (y = y1;y <= (y2 - lines);++y)
  126.         {
  127.       saveofs = offset;
  128.           for (x = x1;x <= x2;++x)
  129.         screen[offset++] = screen[nextofs++];
  130.       offset = saveofs + width;
  131.       nextofs = offset + width;
  132.     }
  133.       while (y <= y2)
  134.         {
  135.       saveofs = offset;
  136.           for (x = x1;x <= x2;++x)
  137.             screen[offset++] = clearpair;
  138.       offset = saveofs + width;
  139.       ++y;
  140.     }
  141.     }
  142.    else
  143.     {
  144.       // Scroll the area down a number of lines //
  145.       offset = x1 + (y2 * width);
  146.       nextofs = offset - width;
  147.       for (y = y2;y >= (y1 - lines);--y)
  148.         {
  149.       saveofs = offset;
  150.           for (x = x1;x <= x2;++x)
  151.         screen[offset++] = screen[nextofs++];
  152.       offset = saveofs - width;
  153.       nextofs = offset - width;
  154.     }
  155.       while (y >= y1)
  156.         {
  157.       saveofs = offset;
  158.           for (x = x1;x <= x2;++x)
  159.             screen[offset++] = clearpair;
  160.       offset = saveofs - width;
  161.       --y;
  162.     }
  163.     }
  164. // #endif    DOOBERY
  165. #ifdef    DOOBERY        // Comment this code out - it doesn't work :-(
  166.       // Scroll the area up a number of lines //
  167.       offset = x1 + (y1 * width);
  168.       nextofs = offset + width;
  169.       linewid = (x2 - x1 + 1) << 1;
  170.       for (y = y1;y <= (y2 - lines);++y)
  171.         {
  172.       memcpy (screen + offset,screen + nextofs,linewid);
  173.       offset += width;
  174.       nextofs += width;
  175.     }
  176.       while (y <= y2)
  177.         {
  178.       saveofs = offset;
  179.           for (x = x1;x <= x2;++x)
  180.             screen[offset++] = clearpair;
  181.       offset = saveofs + width;
  182.       ++y;
  183.     }
  184.     }
  185.    else
  186.     {
  187.       // Scroll the area down a number of lines //
  188.       offset = x1 + (y2 * width);
  189.       nextofs = offset - width;
  190.       linewid = (x2 - x1 + 1) << 1;
  191.       for (y = y2;y >= (y1 - lines);--y)
  192.         {
  193.       memcpy (screen + offset,screen + nextofs,linewid);
  194.       offset += width;
  195.       nextofs += width;
  196.     }
  197.       while (y >= y1)
  198.         {
  199.       saveofs = offset;
  200.           for (x = x1;x <= x2;++x)
  201.             screen[offset++] = clearpair;
  202.       offset = saveofs - width;
  203.       --y;
  204.     }
  205.     }
  206. #endif    DOOBERY
  207. #ifdef    UWPC_DOS
  208.   if (attop)
  209.     {
  210.       if (HardwareScreen.dialogenabled)
  211.         top (attop);        // Redraw window when there is a dialog box.
  212.        else
  213.         HardwareScreen.scroll (x1,y1,x2,y2,lines,attribute);
  214.     }
  215. #else
  216.   repaint (x1,y1,x2,y2);    // Invalidate the scrolling area.
  217. #endif
  218. } // UWDisplay::scroll //
  219.  
  220. void    UWDisplay::setcurs (void)
  221. {
  222. #ifdef    UWPC_DOS
  223.   if (attop && !HardwareScreen.dialogenabled)
  224.     HardwareScreen.cursor (x,y);
  225. #endif
  226. } // UWDisplay::setcurs //
  227.  
  228. UWDisplay::UWDisplay (int number)
  229. {
  230. #ifdef    UWPC_DOS
  231.   width = HardwareScreen.width;
  232.   height = HardwareScreen.height - 1;
  233. #else
  234.   char title[10] = "UW/PC - N";
  235.   RECT rect;
  236.   int wid,ht,changed;
  237.   width = 80;
  238.   height = 24;
  239.   wNumber = number;    // Record the window number for later.
  240.   hWnd = NULL;        // Mark the Windows 3.0 window as not present.
  241. #endif
  242.   screen = new unsigned [width * height];
  243.   attop = 0;
  244. #ifdef    UWPC_DOS
  245.   attr = HardwareScreen.attributes[ATTR_NORMAL];
  246. #else
  247.   attr = UWConfig.NewAttrs[ATTR_NORMAL];
  248. #endif
  249.   scrollattr = attr;
  250.   x = 0;
  251.   y = 0;
  252.   wrap52 = 0;
  253.   if (screen == 0)
  254.     width = 0;
  255.    else
  256.     {
  257. #ifdef    UWPC_WINDOWS
  258.       // Create the Windows 3.0 window associated with this display object //
  259.       title[8] = number + '0';
  260.       curson = 0;
  261.       hWnd = CreateWindow ((number == 0 ? "UWPCMainClass" : "UWPCSessClass"),
  262.                               // Name of window class.
  263.                      (number == 0 ? "Unix Windows" : title),
  264.                            // Window name.
  265.                WS_OVERLAPPEDWINDOW,    // Style of window to use.
  266.                CW_USEDEFAULT,    // Default initial position.
  267.                CW_USEDEFAULT,
  268.                CW_USEDEFAULT,    // Size of the window.
  269.                CW_USEDEFAULT,
  270.                NULL,        // Parent (none)
  271.                NULL,        // Menu handle - use default.
  272.                hInstance,        // Program instance.
  273.                (LPSTR)this);    // Extra information.
  274.       if (!hWnd)
  275.         {
  276.       width = 0;            // Creation failed.
  277.       return;
  278.     }
  279. #endif
  280.       clear ();
  281. #ifdef    UWPC_WINDOWS
  282.       // Adjust the "Functions" menu to contain the function keys //
  283.       int func;
  284.       HMENU hMenu;
  285.       char funckey[29];
  286.       hMenu = GetMenu (hWnd);
  287.       funckey[0] = 'F';        // Add skeleton "F&n \t" at start.
  288.       funckey[1] = '&';
  289.       funckey[3] = ' ';
  290.       funckey[4] = '\t';
  291.       funckey[25] = '.';    // Add "..." to end of string
  292.       funckey[26] = '.';    // for long function key definitions.
  293.       funckey[27] = '.';
  294.       funckey[28] = '\0';
  295.       for (func = IDM_F1;func <= IDM_F10;++func)
  296.         {
  297.       if (func >= IDM_F10)
  298.         strcpy (funckey,"F1&0\t");
  299.        else
  300.         funckey[2] = '1' + func - IDM_F1;
  301.       if (UWConfig.FKeys[func - IDM_F1][0] == '\0')
  302.         strcpy (funckey + 5,"<nothing>");
  303.        else
  304.         strncpy (funckey + 5,UWConfig.FKeys[func - IDM_F1],20);
  305.       ModifyMenu (hMenu,func,MF_BYCOMMAND | MF_STRING,func,funckey);
  306.     } /* for */
  307.  
  308.       // Resize the window to the required width and height.
  309.       GetWindowRect (hWnd,&rect);
  310.       wid = UWFontWidth * width + GetSystemMetrics (SM_CXFRAME) * 2;
  311.       ht  = UWFontHeight * height + GetSystemMetrics (SM_CYFRAME) * 2 +
  312.                     GetSystemMetrics (SM_CYCAPTION) +
  313.                     GetSystemMetrics (SM_CYMENU) + 2;
  314.       changed = 0;
  315.       if ((rect.right - rect.left + 1) > wid)
  316.         {
  317.       rect.right = wid + rect.left - 1;
  318.       changed = 1;
  319.     }
  320.       if ((rect.bottom - rect.top + 1) > ht)
  321.         {
  322.       rect.bottom = ht + rect.top - 1;
  323.       changed = 1;
  324.     }
  325.       if (changed)
  326.         MoveWindow (hWnd,rect.left,rect.top,rect.right - rect.left + 1,
  327.             rect.bottom - rect.top + 1,0);
  328.       curson = 1;
  329.       ShowWindow (hWnd,SW_SHOW);
  330.       UpdateWindow (hWnd);
  331. #endif
  332.     }
  333. } // UWDisplay::UWDisplay //
  334.  
  335. UWDisplay::~UWDisplay (void)
  336. {
  337.   if (screen)
  338.     delete screen;
  339. #ifdef    UWPC_WINDOWS
  340.   if (hWnd)
  341.     DestroyWindow (hWnd);
  342. #endif
  343. } // UWDisplay::~UWDisplay //
  344.  
  345. // Bring the display to the top on the screen, or
  346. // disable it from being the top display.  This must
  347. // only be called by the UW protocol handling classes,
  348. // never explicitly by clients.
  349. void    UWDisplay::top    (int bringup)
  350. {
  351.   if (bringup)
  352.     {
  353. #ifdef    UWPC_DOS
  354.       // Mark the display as being at top and then redraw it //
  355.       int offset,endofs,y;
  356.       attop = 1;
  357.       endofs = width * height;
  358.       y = 0;
  359.       for (offset = 0;offset < endofs;offset += width)
  360.         HardwareScreen.line (0,y++,screen + offset,width);
  361.       setcurs ();
  362.       if (!HardwareScreen.dialogenabled)
  363.         HardwareScreen.shape ((CursorShapes)UWConfig.CursorSize);
  364. #else
  365.       attop = 1;
  366.       if (IsIconic (hWnd))
  367.         ShowWindow (hWnd,SW_RESTORE);    // De-iconify the window.
  368.        else
  369.         BringWindowToTop (hWnd);    // Bring to the top.
  370. #endif
  371.     }
  372.    else
  373.     attop = 0;
  374. } // UWDisplay::top //
  375.  
  376. // Send a character to the display directly with no
  377. // translation of control characters.  If 'vt52wrap'
  378. // is non-zero, the VT52 line wrapping scheme is used.
  379. void    UWDisplay::send    (int ch,int vt52wrap)
  380. {
  381.   if (wrap52)
  382.     {
  383.       cr ();
  384.       lf ();
  385.     }
  386.   CURSOR_OFF ();
  387.   show (x,y,((unsigned)(ch & 255)) | ((unsigned)(attr << 8)));
  388.   ++x;
  389.   if (x >= width)
  390.     {
  391.       if (vt52wrap)
  392.         {
  393.       wrap52 = 1;
  394.       --x;
  395.     }
  396.        else
  397.     {
  398.       cr ();
  399.       lf ();
  400.     }
  401.     }
  402.   setcurs ();
  403.   CURSOR_ON ();
  404. } // UWDisplay::send //
  405.  
  406. // Perform a carriage return operation on the display.
  407. void    UWDisplay::cr    (void)
  408. {
  409.   CURSOR_OFF ();
  410.   x = 0;
  411.   wrap52 = 0;
  412.   setcurs ();
  413.   CURSOR_ON ();
  414. } // UWDisplay::cr //
  415.  
  416. // Perform a line feed operation on the display.  When
  417. // the cursor is on the last display line, the display
  418. // will be scrolled one line up in the scrolling colour.
  419. void    UWDisplay::lf    (void)
  420. {
  421.   CURSOR_OFF ();
  422.   ++y;
  423.   if (y >= height)
  424.     {
  425.       // Scroll the display up one line //
  426.       --y;
  427.       scroll (0,0,width - 1,height - 1,1,scrollattr);
  428.     }
  429.   wrap52 = 0;
  430.   setcurs ();
  431.   CURSOR_ON ();
  432. } // UWDisplay::lf //
  433.  
  434. // Move back one position on the display.  If 'wrap'
  435. // is non-zero, wrap to previous lines as well.
  436. void    UWDisplay::bs    (int wrap)
  437. {
  438.   CURSOR_OFF ();
  439.   --x;
  440.   if (x < 0)
  441.     {
  442.       if (wrap && y > 0)
  443.         {
  444.       --y;
  445.       x = width - 1;
  446.     }
  447.        else
  448.         x = 0;
  449.     }
  450.   wrap52 = 0;
  451.   setcurs ();
  452.   CURSOR_ON ();
  453. } // UWDisplay::bs //
  454.  
  455. // Tab across to the next tab stop of the supplied size.
  456. void    UWDisplay::tab (int vt52wrap,int tabsize)
  457. {
  458.   do
  459.     {
  460.       send (' ',vt52wrap);
  461.     }
  462.   while ((x % tabsize) != 0);
  463. } // UWDisplay::tab //
  464.  
  465. // Ring the terminal bell - this directly calls
  466. // the hardware routines to ring it.
  467. void    UWDisplay::bell (void)
  468. {
  469. #ifdef    UWPC_DOS
  470.   HardwareScreen.bell ();    // Call the BIOS for the DOS bell.
  471. #else
  472.   if (UWConfig.BeepEnable)
  473.     MessageBeep (0);        // Use this as the Windows 3.0 bell for now.
  474. #endif
  475. } // UWDisplay::bell //
  476.  
  477. // Move the cursor to a new position on the display.
  478. // The origin is at (0,0).
  479. void    UWDisplay::move    (int newx,int newy)
  480. {
  481.   CURSOR_OFF ();
  482.   if (newx >= 0 && newx < width && newy >= 0 && newy < height)
  483.     {
  484.       x = newx;
  485.       y = newy;
  486.     }
  487.   wrap52 = 0;
  488.   setcurs ();
  489.   CURSOR_ON ();
  490. } // UWDisplay::move //
  491.  
  492. // Clear the display according to a particular clearing
  493. // type.  This function does not move the cursor position.
  494. void    UWDisplay::clear    (int clrtype)
  495. {
  496.   switch (clrtype)
  497.     {
  498.       case CLR_ALL:
  499.               scroll (0,0,width - 1,height - 1,0,scrollattr);
  500.         break;
  501.       case CLR_END_SCREEN:
  502.               if (y < (height - 1))
  503.           scroll (0,y + 1,width - 1,height - 1,0,scrollattr);
  504.         /* Fall through to end of line clear */
  505.       case CLR_END_LINE:
  506.               scroll (x,y,width - 1,y,0,scrollattr);
  507.         break;
  508.       case CLR_ST_SCREEN:
  509.               if (y > 0)
  510.           scroll (0,0,width - 1,y - 1,0,scrollattr);
  511.         /* Fall through to start of line clear */
  512.       case CLR_ST_LINE:
  513.               if (x > 0)
  514.                 scroll (0,y,x - 1,y,0,scrollattr);
  515.         break;
  516.       default:    break;
  517.     }
  518.   wrap52 = 0;
  519. } // UWDisplay::clear //
  520.  
  521. // Insert a new line on the display.
  522. void    UWDisplay::insline    (void)
  523. {
  524.   scroll (0,y,width - 1,height - 1,-1,scrollattr);
  525.   wrap52 = 0;
  526. } // UWDisplay::insline //
  527.  
  528. // Delete the current line from the display.
  529. void    UWDisplay::delline    (void)
  530. {
  531.   scroll (0,y,width - 1,height - 1,1,scrollattr);
  532.   wrap52 = 0;
  533. } // UWDisplay::delline //
  534.  
  535. // Insert a new character into the current line.
  536. // If 'ch' is -1, then insert a blank and don't move cursor.
  537. void    UWDisplay::inschar    (int ch)
  538. {
  539.   int offset,xval;
  540. #ifdef    UWPC_DOS
  541.   int start;
  542. #endif
  543.   unsigned pair,temp;
  544.   offset = x + (y * width);
  545. #ifdef    UWPC_DOS
  546.   start = offset;
  547. #endif
  548.   xval = x;
  549.   if (ch != -1)
  550.     pair = (ch & 255) | (attr << 8);
  551.    else
  552.     pair = ' ' | (attr << 8);
  553.   while (xval < width)
  554.     {
  555.       // Swap the insertion character with the screen character //
  556.       temp = screen[offset];
  557.       screen[offset] = pair;
  558.       pair = temp;
  559.       ++offset;
  560.       ++xval;
  561.     }
  562. #ifdef    UWPC_WINDOWS
  563.   if (x < (width - 1))
  564.     repaint (x,y,width - 2,y);
  565. #else
  566.   if (attop)        // Redraw the screen line.
  567.     HardwareScreen.line (x,y,screen + start,width - x + 1);
  568. #endif
  569.   if (ch != -1)
  570.     send (ch);
  571. } // UWDisplay::inschar //
  572.  
  573. // Delete the current character, and append the given
  574. // character to the current line.
  575. void    UWDisplay::delchar    (int ch)
  576. {
  577.   int offset,xval;
  578. #ifdef    UWPC_DOS
  579.   int start;
  580. #endif
  581.   offset = x + (y * width);
  582. #ifdef    UWPC_DOS
  583.   start = offset;
  584. #endif
  585.   xval = x;
  586.   while (xval < (width - 1))
  587.     {
  588.       // Move the characters back one on the line //
  589.       screen[offset] = screen[offset + 1];
  590.       ++offset;
  591.       ++xval;
  592.     }
  593.   // Place the given character at the line's end //
  594.   screen[offset] = (ch & 255) | (scrollattr << 8);
  595. #ifdef    UWPC_DOS
  596.   if (attop)        // Redraw the screen line after the deletion.
  597.     HardwareScreen.line (x,y,screen + start,width - x + 1);
  598. #else
  599.   repaint (x,y,width - 1,y);
  600. #endif
  601.   wrap52 = 0;
  602. } // UWDisplay::delchar //
  603.  
  604. // Scroll the screen up or down one line.
  605. void    UWDisplay::scrollscreen (int up)
  606. {
  607.   if (up)
  608.     scroll (0,0,width - 1,height - 1,1,scrollattr);
  609.    else
  610.     scroll (0,0,width - 1,height - 1,-1,scrollattr);
  611. } // UWDisplay::scrollscreen //
  612.  
  613. // If the screen has a status line, then set it to the
  614. // given string, otherwise ignore the request.  If "str"
  615. // is NULL, then clear the status line (i.e. don't display).
  616. void    UWDisplay::status    (char *str,int length)
  617. {
  618. #ifdef    UWPC_DOS        // Only display status line in DOS version.
  619.   int x=0;
  620.   unsigned attrmask;
  621.   if (str != 0)
  622.     switch (UWConfig.StatusPosn)
  623.       {
  624.         case STATUS_LEFT:
  625.         case STATUS_LEFT_SQUASH:
  626.               x = 0;
  627.         if (UWConfig.StatusPosn == STATUS_LEFT)
  628.           attrmask = HardwareScreen.attributes[ATTR_STATUS];
  629.          else
  630.           attrmask = 0x07;
  631.         if (length < width)
  632.           HardwareScreen.scroll (length,
  633.                        HardwareScreen.height - 1,
  634.                            HardwareScreen.width - 1,
  635.                      HardwareScreen.height - 1,
  636.                      0,attrmask);
  637.               break;
  638.         case STATUS_RIGHT:
  639.         case STATUS_RIGHT_SQUASH:
  640.               if (length <= width)
  641.           x = width - length;
  642.          else
  643.                 x = 0;
  644.         if (UWConfig.StatusPosn == STATUS_RIGHT)
  645.           attrmask = HardwareScreen.attributes[ATTR_STATUS];
  646.          else
  647.           attrmask = 0x07;
  648.         if (length < width)
  649.           HardwareScreen.scroll (0,HardwareScreen.height - 1,
  650.                            width - length - 1,
  651.                      HardwareScreen.height - 1,
  652.                      0,attrmask);
  653.               break;
  654.         case STATUS_CENTRE:
  655.         case STATUS_CENTRE_SQUASH:
  656.               if (length <= width)
  657.           x = (width - length) / 2;
  658.          else
  659.                 x = 0;
  660.         if (UWConfig.StatusPosn == STATUS_CENTRE)
  661.           attrmask = HardwareScreen.attributes[ATTR_STATUS];
  662.          else
  663.           attrmask = 0x07;
  664.         HardwareScreen.scroll (0,HardwareScreen.height - 1,
  665.                          HardwareScreen.width - 1,
  666.                        HardwareScreen.height - 1,
  667.                        0,attrmask);
  668.               break;
  669.       } // switch //
  670.   if (x < 0)
  671.     x = 0;
  672.   if (str != 0)
  673.     {
  674.       attrmask = HardwareScreen.attributes[ATTR_STATUS] << 8;
  675.       while (x < width && *str)
  676.         {
  677.           if (*str == '\001')
  678.             attrmask = HardwareScreen.attributes[ATTR_HIGH_STATUS] << 8;
  679.            else if (*str == '\002')
  680.             attrmask = HardwareScreen.attributes[ATTR_STATUS] << 8;
  681.            else
  682.             HardwareScreen.draw (x++,height,attrmask | (*str & 255));
  683.           ++str;
  684.         }
  685.     }
  686.    else
  687.     {
  688.       attrmask = 0x0700;    // Clear status line (so it's not displayed)
  689.       x = 0;
  690.     }
  691.   if (str == 0 || UWConfig.StatusPosn < STATUS_LEFT_SQUASH)
  692.     {
  693.       attrmask |= ' ';
  694.       while (x < width)
  695.         HardwareScreen.draw (x++,height,attrmask);
  696.     }
  697. #endif
  698. } // UWDisplay::status //
  699.  
  700. // Mark a rectangle on the screen for cut-and-paste.
  701. // Two calls to this routine will remove the mark.
  702. void    UWDisplay::markcut (int x1,int y1,int x2,int y2)
  703. {
  704.   int temp,x,y,offset,nextline,length,start;
  705.   unsigned pair;
  706.   if (x1 > x2)
  707.     {
  708.       temp = x1;
  709.       x1 = x2;
  710.       x2 = temp;
  711.     }
  712.   if (y1 > y2)
  713.     {
  714.       temp = y1;
  715.       y1 = y2;
  716.       y2 = temp;
  717.     }
  718.   offset = x1 + y1 * width;
  719.   start = offset;
  720.   length = x2 - x1 + 1;
  721.   nextline = width - length;
  722.   for (y = y1;y <= y2;++y)
  723.     {
  724.       for (x = x1;x <= x2;++x)
  725.         {
  726.       // Flip the attribute colours in the screen pair //
  727.       pair = screen[offset];
  728.       screen[offset++] = (pair & 0x88FF) | ((pair & 0x0700) << 4) |
  729.                       ((pair & 0x7000) >> 4);
  730.     }
  731. #ifdef    UWPC_DOS
  732.       HardwareScreen.line (x1,y,screen + start,length);
  733. #endif
  734.       offset += nextline;
  735.       start += width;
  736.     }
  737. } // UWDisplay::markcut //
  738.  
  739. // Copy screen data into a clipboard buffer.  The
  740. // length of the written data is returned.
  741. int    UWDisplay::copycut (int x1,int y1,int x2,int y2,char *buffer)
  742. {
  743.   int temp,x,y,offset,nextline,length;
  744.   if (x1 > x2)
  745.     {
  746.       temp = x1;
  747.       x1 = x2;
  748.       x2 = temp;
  749.     }
  750.   if (y1 > y2)
  751.     {
  752.       temp = y1;
  753.       y1 = y2;
  754.       y2 = temp;
  755.     }
  756.   offset = x1 + y1 * width;
  757.   nextline = width - (x2 - x1 + 1);
  758.   length = 0;
  759.   for (y = y1;y <= y2;++y)
  760.     {
  761.       for (x = x1;x <= x2;++x)
  762.         {
  763.       *buffer++ = screen[offset++] & 255;
  764.       ++length;
  765.     }
  766.       while (length > 0 && *(buffer - 1) == ' ')
  767.         {
  768.       // Move back to eliminate trailing spaces on the line //
  769.       --length;
  770.       --buffer;
  771.     }
  772.       if (y != y2)
  773.         {
  774.       *buffer++ = '\r';    // Paste ^M at end of each line except last.
  775.       ++length;
  776.     }
  777.       offset += nextline;
  778.     }
  779.   return (length);        // Return the length of the paste buffer.
  780. } // UWDisplay::copycut //
  781.