home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 04 / screen.cpp < prev    next >
C/C++ Source or Header  |  1992-02-05  |  19KB  |  777 lines

  1. // screen.cpp RHS 7/28/91
  2.  
  3. #include"screen.h"
  4. #include<malloc.h>
  5. #include<stdarg.h>
  6. #include<stdio.h>
  7. #include<string.h>
  8. #include<process.h>
  9. //#include"memwset.h"
  10.  
  11. OrgScreen Screen::orgScreen;
  12. ScrDeskTop *Screen::DeskTop;
  13.  
  14. #ifdef OLD
  15. int Screen::numlines;
  16. int Screen::numcols;
  17. char far *Screen::screenBuf;
  18. unsigned far *Screen::curpos;
  19. BYTE Screen::currAttr;
  20. BYTE Screen::mode;
  21. #else
  22. SCRPARAMS Screen::params;
  23. #endif
  24.  
  25. BOOL Screen::wait_for_retrace;
  26. BOOL Screen::buffered;
  27. unsigned Screen::bufsize;
  28. char far *Screen::buffer;
  29. char *Screen::workbuffer;
  30. char *Screen::workbuf2;
  31. void far *Screen::org_screen_image;
  32. WORD Screen::org_screen_size;
  33. WORD Screen::org_screen_curpos;
  34.  
  35. Screen *ScreenPtr = NULL;
  36.  
  37. Screen::Screen(void)
  38.     {
  39.     if(ScreenPtr)
  40.         return;
  41.     ScreenPtr = this;
  42.     orgScreen.params.screenBuf = NULL;
  43.     DeskTop = NULL;
  44.     BOOL printf_enabled = TRUE;
  45.     workbuffer = (printf_enabled) ? new char[DEFAULTLINELEN] : NULL;
  46.     workbuf2 = new char[DEFAULTLINELEN];
  47.     }
  48.  
  49. SCRPARAMS Screen::GetVidModeParams(BYTE *cols)
  50.     {
  51.     SCRPARAMS p;
  52.  
  53.     p.mode = VidGetMode(cols); //(newmode != VIDMODE_DEFAULT ? VidGetMode(cols) : orgmode);
  54.     p.numcols = *cols;
  55.     if(p.mode == VIDMODE_C80)
  56.         if(*((char far *)0x00400084) > 24)  
  57.             p.mode = VIDMODE_EGAVGA;
  58.     p.numlines = (p.mode != VIDMODE_EGAVGA) ? 25 : *((char far *)0x00400084) + 1;
  59.     p.screenBuf = (p.mode == VIDMODE_MONO) ? (char far *)0xB0000000 : 
  60.         (char far *)0xB8000000;
  61.     p.currAttr = p.screenBuf[1];
  62.  
  63.     BYTE row,col;
  64.     WORD start_stop;
  65.     _AH = 3;
  66.     _BH = 0;
  67.     asm int 10h;
  68.     row = _DH;
  69.     col = _DL;
  70.     start_stop = _CX;
  71.     p.curpos = (unsigned far *)&p.screenBuf[(row * *cols)+(col*2)];
  72.     p.currow = row;
  73.     p.curcol = col;
  74.     p.cursorSize = start_stop;
  75.  
  76.     return p;
  77.     }
  78.  
  79. void Screen::Init(int newmode, BYTE desktop_colors, BYTE screen_colors)
  80.     {
  81.     BYTE cols;
  82.  
  83.     if(!orgScreen.params.screenBuf)
  84.         {
  85.         orgScreen.params = GetVidModeParams(&cols);
  86.  
  87.             // allocate space to save screen buffer and save it
  88.         org_screen_size = orgScreen.params.numlines*orgScreen.params.numcols;
  89.         if(org_screen_image = farmalloc(org_screen_size*2L))
  90.             CpyWords(org_screen_image,orgScreen.params.screenBuf,
  91.                 org_screen_size);
  92.         }
  93.  
  94.     if(newmode == VIDMODE_DEFAULT)
  95.         newmode = VidGetMode(NULL);
  96.     VidSetMode(newmode);
  97.     params = GetVidModeParams(&cols);
  98.  
  99.     wait_for_retrace = (params.mode != VIDMODE_MONO) &&
  100.         (!CheckSysCopyRight((char far *)0xF000FFEAL,"COMPAQ")) &&
  101.         (!IsEgaVga());
  102.     params.currAttr = screen_colors;
  103.  
  104.     buffered = FALSE;
  105.     buffer = NULL;
  106.     bufsize = 0;
  107. //    printf("newmode=%d\n",newmode);getchar();
  108.     if(DeskTop)
  109.         delete DeskTop;
  110.     DeskTop = new ScrDeskTop(desktop_colors, screen_colors);
  111.     }
  112.  
  113. void Screen::Paint(void)
  114.     {
  115.     if(DeskTop)
  116.         DeskTop->Paint();
  117.     else
  118.         Clear();
  119.     }
  120.  
  121. BOOL near pascal Screen::CheckSysCopyRight(char far *ROMaddress, 
  122.     char *Copyright)
  123.     {
  124.     while (*Copyright)
  125.         if(*Copyright++ != *ROMaddress++) 
  126.             return 0;
  127.     return 1;
  128.     }
  129.  
  130. BOOL near pascal IsEgaVga(void)
  131.     {
  132.     asm mov     bl,10h                 /* make sure he has an EGA/VGA */
  133.     asm mov     ah,12h
  134.     asm int     10h
  135.     asm cmp     bl,10h
  136.     asm je      NotEgaVga
  137. EgaVga:
  138.     return TRUE;
  139. NotEgaVga:
  140.     return FALSE;
  141.     }
  142.  
  143. void Screen::SetTextMode(int newmode)
  144.   {
  145.   Init(newmode);
  146.   }
  147.  
  148. Screen::~Screen(void)
  149.     {
  150.     if(this == ScreenPtr)
  151.         {
  152.         if(workbuffer)
  153.             {
  154.             delete workbuffer;
  155.             workbuffer = NULL;
  156.             }
  157.         if(workbuf2)
  158.             {
  159.             delete workbuf2;
  160.             workbuf2 = NULL;
  161.             }
  162.         if(DeskTop)
  163.             {
  164.             delete DeskTop;
  165.             DeskTop = NULL;
  166.             }
  167.         params = orgScreen.params;
  168.         }
  169.     if(this == ScreenPtr && orgScreen.params.screenBuf)
  170.         {
  171.         Init(params.mode);
  172. //        Paint();
  173.         if(org_screen_image)
  174.             {
  175.             CpyWords(params.screenBuf,org_screen_image,org_screen_size);
  176.             farfree(org_screen_image);
  177.             org_screen_image = NULL;
  178.             params.cursorSize = orgScreen.params.cursorSize;
  179.             Cursor(SCR_CURSOR_ON);
  180.             Cursor(orgScreen.params.currow,orgScreen.params.curcol);
  181.             }
  182.         }
  183.     }
  184.  
  185. void Screen::SetForeGround(unsigned char c)
  186.     {
  187.     (params.currAttr &= 0xf0) |= c;                           // clear foreground bits
  188.     }
  189.  
  190. void Screen::SetBackGround(unsigned char c)
  191.     {
  192.     (params.currAttr &= 0x0f) |= MakeBG(c);     // clear background bits
  193.     }
  194.  
  195. void Screen::Clear(int row, int col, int erow, int ecol, BYTE colors)
  196.     {
  197. #ifdef NOTYET
  198.     unsigned word = MakeCell(' ',params.currAttr);
  199.  
  200. // NOTE: Change this to use a snow-safe routine
  201.     memwset(params.screenBuf,word,params.numlines*params.numcols*2);
  202. #else
  203.     int i,j;
  204.  
  205.     j = (ecol-col);
  206.     if(j+col > params.numcols)
  207.         j = params.numcols-col;
  208.     Cursor(row,col);
  209.     WORD w = MakeCell(' ',colors);
  210.     for(i = row; i < erow && i < params.numlines; i++)
  211.         {
  212.         SetWords(params.curpos,w,j);
  213.         //Printf("%*s",j,"");
  214.         Cursor(i,col);
  215.         }
  216.     Cursor(row,col);
  217. #endif
  218.     }
  219.  
  220. void cdecl Screen::Printf(char *fmt, ...)
  221.     {
  222.     if(!workbuffer)
  223.         return;
  224.  
  225.     va_list argptr;
  226.  
  227.     va_start(argptr,fmt);
  228.     vsprintf(workbuffer,fmt,argptr);
  229.     va_end(arg_ptr);
  230.  
  231.     if(strchr(workbuffer,'\n'))
  232.         {
  233.         char *p = workbuffer, *q = &workbuffer[strlen(workbuffer)], *r = workbuffer;
  234.         unsigned count, width = params.numcols*2;
  235.  
  236.         while((p < q) && (p = strchr(p,'\n')))
  237.             {
  238.             *p = '\0';
  239.             Write(r);
  240.             p++;
  241.             r = p;
  242.             count = (char far *)params.curpos-params.screenBuf;
  243.             params.curpos = (unsigned far *)(params.screenBuf + (((count / width)+1)*width));
  244.             
  245.             }
  246.         }
  247.     else
  248.         Write(workbuffer);
  249.     }
  250.  
  251. void cdecl Screen::AtSay(int row,int col, char *fmt, ...)
  252.     {
  253.     if(!workbuffer)
  254.         return;
  255.  
  256.     va_list argptr;
  257.  
  258.     va_start(argptr,fmt);
  259.     vsprintf(workbuffer,fmt,argptr);
  260.     va_end(arg_ptr);
  261.  
  262.     Cursor(row,col);
  263.     Write(workbuffer);
  264.     }
  265.  
  266. void Screen::Buffering(BOOL on)
  267.     {
  268.     if(on)
  269.         {
  270.         if(buffered)
  271.             return;
  272.         buffered = TRUE;
  273.         buffer = (char far *)farmalloc(bufsize = (params.numlines*params.numcols*2));
  274.         VidRamAccess(buffer,params.screenBuf,params.numlines*params.numcols*2);
  275.         }
  276.     else
  277.         {
  278.         if(!buffered)
  279.             return;
  280.         buffered = FALSE;
  281.         VidRamAccess(params.screenBuf,buffer,bufsize);    // flush buffer
  282.         bufsize = 0;
  283.         farfree(buffer);
  284.         buffer = NULL;
  285.         }
  286.     }
  287.  
  288.  
  289. WORD far *Screen::Cursor(int x, int y)
  290.     {
  291.     _BH = 0;
  292.     _DH = x;
  293.     _DL = y;
  294.     _AH = 2;
  295.     asm int 10h
  296.     return params.curpos = (unsigned far *)
  297.         (¶ms.screenBuf[(x*params.numcols*2)+(y*2)]);
  298.     }
  299.  
  300. void Screen::Cursor(BOOL on)
  301.     {
  302.     if(on)
  303.         {
  304.         _CX = params.cursorSize;
  305.         _AH = 1;
  306.         asm int 10h;
  307.         }
  308.     else
  309.         {
  310.         _BH = 0;
  311.         _AH = 3;
  312.         asm int 10h;
  313.         params.cursorSize = _CX;
  314.         _CX = 0x2000;
  315.         _AH = 1;
  316.         asm int 10h;
  317.         }
  318.     }
  319.  
  320.  
  321. void Screen::Write(char *str,WORD clr)
  322.     {
  323.     Write((unsigned char *)str, clr, strlen(str));
  324.     }
  325.  
  326. void Screen::Write(unsigned char *str, WORD clr, int len)
  327.     {
  328.     int i;
  329.     unsigned *u = (unsigned *)workbuf2, attrmask;
  330.     
  331.     attrmask = MakeCell(0,clr);
  332.     //((params.currAttr << 8) & 0xff00);
  333.  
  334.     for(i = 0; i < len; i++, u++)
  335.         *u = (attrmask | str[i]);
  336.         
  337.     if(!buffered)
  338.         {
  339.         VidRamAccess(params.curpos,workbuf2,len);
  340.         params.curpos += (len);
  341.         }
  342.     }
  343.  
  344. void Screen::WriteRaw(void far *buf, int len)
  345.     {
  346.     VidRamAccess(params.screenBuf,buf,len);
  347.     }
  348.  
  349. void Screen::Read(char *str)
  350.     {
  351.     Read(str, strlen(str));
  352.     }
  353.  
  354. void Screen::Read(char *str, int len)
  355.     {
  356.     VidRamAccess(str,params.curpos,len);
  357.     }
  358.  
  359. void Screen::ReadRaw(void far *buf, int len)
  360.     {
  361.     VidRamAccess(buf,params.screenBuf,len);
  362.     }
  363.  
  364. void Screen::FlushBuffer(void)
  365.     {
  366.     if(!buffered)
  367.         return;
  368.     VidRamAccess(params.screenBuf,buffer,bufsize);
  369.     }
  370.  
  371.  
  372. // VidRamAccess - moves len bytes of video RAM from scr to dst and checks
  373. //    for snow
  374.  
  375. void near pascal Screen::VidRamAccess(void far *dst, void far *src, int len)
  376.     {
  377. #if defined(JUNK)
  378.     int Snow;
  379.  
  380.     Snow = wait_for_retrace;
  381.  
  382.     asm    push    ds
  383.     asm    mov    cx, len        // Length value into CX 
  384.     asm    jcxz    Exit
  385.     asm    les    di, dst        // Get pointers to data area 
  386.     asm    lds    si, src
  387.  
  388.     asm    cld                // Setup move direction 
  389.     asm    cmp    si, di        // Check for move direction 
  390.     asm    jae    SnowTest    // Moving down?, then forward move ok 
  391.     asm    mov    ax, cx        // Nope, then start at other end 
  392.     asm    dec    ax
  393.     asm    shl    ax, 1
  394.     asm    add    si, ax
  395.     asm    add    di, ax
  396.     asm    std
  397.  
  398. SnowTest:
  399.     asm    cmp    word ptr Snow, 0    // Does video card snow ? 
  400.     asm    jnz    StopSnow    // Yes, wait for retrace 
  401.     asm    rep    movsw        // Suppose to do both, do normal move 
  402.     asm    jmp    short Exit    // All done 
  403.  
  404. StopSnow:
  405.     asm    mov    dx, 3DAh    // Suppose to wait, Point DX to CGA status port 
  406.     asm    mov    ax, es        // See if both are in video seg 
  407.     asm    mov    bx, ds
  408.     asm    cmp    ax, bx
  409.     asm    je    VIOStopSnow    // Have to wait to and fro 
  410.  
  411. Wait4HRetrace:
  412.     asm    cli                // No ints during critical section 
  413.  
  414. Synchronize:
  415.     asm    in    al, dx        // Get 6845 status 
  416.     asm    ror    al, 1        // In horizontal retrace ? 
  417.     asm    jc    Synchronize    // If on, wait for cycle to end 
  418.  
  419. WaitForNext:
  420.     asm    in    al, dx        // Get 6845 status 
  421.     asm    ror    al, 1        // In horizontal retrace ? 
  422.     asm    jnc    WaitForNext    // No, wait for it to begin 
  423.     asm    movsw            // Move video ram word 
  424.     asm    sti                // Allow interrupts 
  425.     asm    loop    Wait4HRetrace   // Next byte 
  426.     asm    jmp    short Exit
  427.  
  428. VIOStopSnow:
  429. VInWait4HRetrace:
  430.     asm    cli                // No ints during critical section 
  431.  
  432. VInSynchronize:
  433.     asm    in    al, dx        // Get 6845 status 
  434.     asm    ror    al, 1        // In horizontal retrace ? 
  435.     asm    jc    VInSynchronize    // If on, wait for cycle to end 
  436.  
  437. VInWaitForNext:
  438.     asm    in    al, dx        // Get 6845 status 
  439.     asm    ror    al, 1        // In horizontal retrace ? 
  440.     asm    jnc    VInWaitForNext    // No, wait for it to begin 
  441.     asm    lodsw            // Get word from video ram 
  442.     asm    sti                // Allow interrupts 
  443.     asm     mov    bx, ax    // Save word
  444.     asm    cli                // No ints during critical section 
  445.  
  446. VOutSynchronize:
  447.     asm    in    al, dx        // Get 6845 status 
  448.     asm    ror    al, 1        // In horizontal retrace ? 
  449.     asm    jc    VOutSynchronize    // If on, wait for cycle to end 
  450.  
  451. VOutWaitForNext:
  452.     asm    in    al, dx        // Get 6845 status 
  453.     asm    ror    al, 1        // In horizontal retrace ? 
  454.     asm    jnc    VOutWaitForNext    // No, wait for it to begin 
  455.     asm    mov    ax, bx        // Get word to store 
  456.     asm    stosw            // Put word in video ram 
  457.     asm    sti                // Allow interrupts 
  458.     asm    loop    VInWait4HRetrace    // Next byte 
  459.  
  460. Exit:
  461.     asm    cld            // Restore Direction Flag 
  462.     asm    pop    ds
  463. #endif
  464. #if defined(JUNK)
  465.     int i;
  466.     if(len % 2)
  467.         {
  468.         BYTE far *dest = (BYTE far *)dst;
  469.         BYTE far *sorc = (BYTE far *)src;
  470.         for(i = 0; i < len; i++)
  471.             dest[i] = sorc[i];
  472.         }
  473.     else
  474.         {
  475.         WORD far *dest = (WORD far *)dst;
  476.         WORD far *sorc = (WORD far *)src;
  477.         for(i = 0; i < len; i++)
  478.             dest[i] = sorc[i];
  479.         }
  480. #else
  481.     CpyWords(dst,src,len);
  482. #endif
  483.     return;
  484.     }
  485.  
  486.     // propogates  'val' starting at 'addr', for 'len' repetitions
  487. void near pascal SetWords(void far *addr, unsigned val, unsigned len)
  488.     {
  489.     asm    les    di, addr
  490.     asm    mov    cx, len
  491.     asm    mov    ax, val
  492.     asm    cld
  493.     asm    rep    stosw
  494.     }
  495.  
  496. void near pascal CpyWords(void far *dst, void far *src, unsigned n)
  497.     {
  498.     asm    mov    dx,ds    
  499.     asm    les     di, dst
  500.     asm lds     si, src
  501.     asm    mov    cx,n
  502. //    asm    shr    cx,1
  503.     asm    cld
  504.     asm    rep    movsw
  505. //    asm    jnc    cpy_end
  506. //    asm    movsb
  507. cpy_end:
  508.     asm    mov    ds,dx
  509.     }
  510.  
  511.  
  512.  
  513. void near pascal VidSetMode(BYTE mode)
  514.     {
  515.     /********** Turbo does this for us ************
  516.     asm push  si
  517.     asm push  di
  518.     ***********************************************/
  519.     asm push  ds
  520.     _AH = VIDSETMODE;
  521.     _AL = mode;
  522.  
  523.     asm push  cx
  524.     asm mov   cx,40h                 /* ds = BIOS video data area */
  525.     asm mov   ds,cx
  526.     asm pop   cx
  527.  
  528.     asm cmp   al,VIDMODE_C80
  529.     asm jne   NotC80
  530.  
  531.     asm mov   ax,1a00h               /* is this an EGA? */
  532.     asm int   10h
  533.     asm cmp   al,1ah  
  534.     asm je    NotEGA
  535.     asm and   byte ptr ds:[87h],0feh /* update BIOS data area */
  536. NotEGA:
  537.     asm mov   ah,1                   /* set cursor size */
  538.     asm mov   cx,0607h
  539.     asm int   10h
  540.     asm mov   ax,VIDMODE_C80
  541.  
  542. NormalCall:
  543.     asm int   10h
  544.     asm jmp   Exit
  545.  
  546. NotC80:
  547.     asm cmp   al,VIDMODE_EGAVGA
  548.     asm jne   NormalCall
  549.  
  550.     IsEgaVga();                     // see if he has EGA
  551.  
  552.     asm cmp   ax,0
  553.     asm je    Exit
  554.  
  555.     asm mov   ax,1112h               /* load 8x8 character set */
  556.     asm xor   bl,bl
  557.     asm int   10h
  558.  
  559.     asm mov   ax,1200h               /* select alternate print-screen routine */
  560.     asm mov   bl,20h
  561.     asm int   10h
  562.  
  563.     asm mov   ax,1a00h               /* is this a VGA? */
  564.     asm int   10h
  565.     asm cmp   al,1ah  
  566.     asm je    Exit
  567.  
  568.     asm or    byte ptr ds:[87h],1    /* update BIOS data area */
  569.  
  570.     asm mov   ah,1                   /* set cursor size */
  571.     asm mov   cx,0600h
  572.     asm int   10h
  573.     asm jmp   Exit
  574.  
  575. Exit:
  576.     asm pop   ds
  577.     /********** Turbo does this for us ************
  578.     asm pop   di
  579.     asm pop   si
  580.     ***********************************************/
  581.     }
  582.  
  583. BYTE near pascal VidGetMode(BYTE *cols)
  584.   {
  585.   /********** Turbo does this for us ************
  586.   asm push  si
  587.   asm push  di
  588.   ***********************************************/
  589.   asm push  ds
  590.   _AH = VIDGETMODE;
  591.  
  592.   asm push  cx
  593.   asm mov   cx,40h                 /* ds = BIOS video data area */
  594.   asm mov   ds,cx
  595.   asm pop   cx
  596.  
  597. //GetMode:
  598.   asm int   10h
  599.   asm cmp   al,VIDMODE_C80
  600.   asm jne   Exit
  601.   asm push  ax
  602.  
  603.   IsEgaVga();
  604.  
  605.   asm or    al,al
  606.   asm pop   ax
  607.   asm jz    Exit
  608.   asm cmp   byte ptr ds:[84h],24
  609.   asm je    Exit
  610.   asm mov   al,VIDMODE_EGAVGA
  611.  
  612. Exit:
  613.   asm pop   ds
  614.   if(cols)
  615.     *cols = _AH;
  616.   /********** Turbo does this for us ************
  617.   asm pop   di
  618.   asm pop   si
  619.   ***********************************************/
  620.   return _AL;
  621.   }
  622.  
  623. ScrDeskTop::ScrDeskTop(BYTE clr, BYTE attr, BYTE fchar)
  624.     {
  625.     fillchar = fchar;
  626.     color = clr;
  627.     attributes = attr;
  628.     }
  629.  
  630. BOOL pascal ScrDeskTop::Paint(void)
  631.     {
  632. #if defined(SNOWCHECK)
  633.     BYTE far *temp;
  634.     int i,j, clientheight, clientwidth;
  635.  
  636.     clientheight = ScreenPtr->Lines();
  637.     clientwidth = ScreenPtr->Columns();
  638.  
  639.     if(!(temp = (BYTE far *)farmalloc(clientheight*clientwidth*2L)))
  640.         return FALSE;
  641.  
  642.  
  643.     j = clientheight * clientwidth * 2;
  644.     for( i = 0; i < j; )
  645.         {
  646.         temp[i++] = fillchar;
  647.         temp[i++] = color;
  648.         }
  649.  
  650.     ScreenPtr->WriteRaw(temp,j);
  651.  
  652.     for( i = 0, j = clientwidth*2; i < j; )
  653.         {
  654.         temp[i++] = ' ';
  655.         temp[i++] = color;
  656.         }
  657.  
  658.     if(attributes & SCR_MENU_BAR)
  659.         {
  660.         clientheight--;
  661.         ScreenPtr->WriteRaw(temp,j);
  662.         }
  663.  
  664.     if(attributes & SCR_STATUS_BAR)
  665.         {
  666.         clientheight--;
  667.         ScreenPtr->VidRamAccess(
  668.             &ScreenPtr->params.screenBuf[(clientheight+1)*clientwidth*2], 
  669.             temp, 
  670.             j);
  671.         }
  672.     farfree(temp);
  673.     return FALSE;
  674. #else
  675.  
  676. #define NEW
  677.     BYTE far *temp;
  678.     int i,j, clientheight, clientwidth;
  679.  
  680.     clientheight = ScreenPtr->Lines();
  681.     clientwidth = ScreenPtr->Columns();
  682.  
  683.     temp = (BYTE far *)ScreenPtr->params.screenBuf;
  684.  
  685.     j = clientheight * clientwidth * 2;
  686. #ifdef NEW
  687.     WORD w = MakeCell(fillchar,color);
  688.     SetWords(temp,w,j/2);
  689. #else
  690.     for( i = 0; i < j; )
  691.         {
  692.         temp[i++] = fillchar;
  693.         temp[i++] = color;
  694.         }
  695. #endif
  696.  
  697.     j = clientwidth*2;
  698.  
  699.     if(attributes & SCR_MENU_BAR)
  700.         {
  701. #ifdef NEW
  702.         w = MakeCell(' ',color);
  703.         SetWords(temp,w,j/2);    
  704. #else
  705.         for( i = 0; i < j; )
  706.             {
  707.             temp[i++] = ' ';
  708.             temp[i++] = color;
  709.             }
  710. #endif
  711.         clientheight--;
  712.         }
  713.  
  714.     if(attributes & SCR_STATUS_BAR)
  715.         {
  716.         clientheight--;
  717.         BYTE far *temp2 = (BYTE far *)
  718.             &ScreenPtr->params.screenBuf[(clientheight+1)*clientwidth*2];
  719. #ifdef NEW
  720.         w = MakeCell(' ',color);
  721.         SetWords(temp2,w,j/2);
  722. #else
  723.         for(i = 0; i < j; i++)
  724.             temp2[i] = temp[i];
  725. #endif
  726.         }
  727.     return FALSE;
  728. #endif
  729.     }
  730.  
  731. void Screen::Exec(char *command, char *args[], char *message)
  732.     {
  733.     void far *screenbuf = farmalloc(params.numlines*params.numcols*2*1L);
  734.  
  735.     if(!screenbuf)
  736.         return;
  737.  
  738.         // save current screen
  739.     CpyWords(screenbuf,params.screenBuf,params.numlines*params.numcols*1L);
  740. // ************************************* ADD facilities to handle change of mode
  741.         // restore original screen image
  742. //    CpyWords(params.screenBuf,org_screen_image,params.numlines*params.numcols*1L);
  743.     Cursor(SCR_CURSOR_ON);                          // turn cursor on
  744.     
  745.     BOOL isDos = FALSE;
  746.     char *p = strstr(strupr(command),"COMMAND.COM");
  747.     if(p && (p == command || p[-1] == '\\' || p[-1] == ':'))
  748.         {
  749.         isDos = TRUE;
  750.         VidSetMode(orgScreen.params.mode);
  751.         _DH = orgScreen.params.numlines-1;
  752.         _DL = orgScreen.params.numcols-1;
  753.         _CX = 0;
  754.         _BH = orgScreen.params.currAttr;
  755.         _AH = 6;
  756.         _AL = orgScreen.params.numlines;
  757.         asm int 10h;
  758.         }
  759.     if(message)
  760.         printf(message);
  761. //    extern int errno;
  762. //    errno = 0;
  763.     spawnvp(P_WAIT,command,args);
  764. //    printf("errno=%d\n",errno);
  765.     if(isDos)
  766.         VidSetMode(params.mode);
  767.  
  768.     Cursor(SCR_CURSOR_OFF);
  769. // ************************************* ADD facilities to handle change of mode
  770. //    CpyWords(org_screen_image,params.screenBuf,params.numlines*params.numcols*1L);
  771.         // restore current screen
  772.     CpyWords(params.screenBuf,screenbuf,params.numlines*params.numcols*1L);
  773.     farfree(screenbuf);
  774.     }
  775.  
  776.  
  777.