home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 December / simtel1292_SIMTEL_1292_Walnut_Creek.iso / msdos / turbopas / bonus507.arc / PSCREEN.ARC / PSCREEN.PAS < prev   
Pascal/Delphi Source File  |  1988-12-13  |  13KB  |  477 lines

  1. {$S-,R-,V-,I-,B-,F-}
  2. {$M 4096,0,20000}
  3.  
  4. {*********************************************************}
  5. {*                  PSCREEN.PAS 5.02                     *}
  6. {*        Copyright (c) TurboPower Software 1988.        *}
  7. {*                 All rights reserved.                  *}
  8. {*********************************************************}
  9.  
  10. program PackedScreenUtility;
  11.   {-Utility for saving and displaying packed windows}
  12.  
  13. uses
  14.   Dos, TpCrt, TpString, TpEdit, TpTsr;
  15.  
  16. type
  17.   String64 = string[64];
  18. const
  19.   ModuleName : string[7] = 'PSCREEN'; {module name for standard interface}
  20.   OurHotKey : Word = $0619;  {Ctrl + LeftShift, 'P'}
  21.   ProgName : string[64] = 'PSCREEN 5.02: A Utility for Saving and Displaying Packed Screens';
  22.   Copyright : string[41] = 'Copyright (c) 1988 by TurboPower Software';
  23.   LoadError : string[25] = 'Unable to install PSCREEN';
  24.   Disable   : Boolean = False;
  25. var
  26.   PWP : PackedWindowPtr;
  27.   MainBufPtr : Pointer;
  28.   Bright,                    {video attributes}
  29.   Dim,
  30.   Border,
  31.   Reverse : Byte;
  32.   MaxRows : Word;
  33.   MaxCols : Word;
  34.   MaxParas : Word;           {maximum space needed for saving the screen}
  35.  
  36.   procedure SetAttributes;
  37.     {-Set the attributes to be used based on the current video mode}
  38.   begin
  39.     case CurrentMode of
  40.      0,                      {BW40}
  41.      2,                      {BW80}
  42.      7 :                     {monochrome}
  43.        begin
  44.          Bright := $F;
  45.          Border := $F;
  46.          Dim := $7;
  47.          Reverse := $70;
  48.         end;
  49.     else                     {color}
  50.      begin
  51.       Bright := $1F;
  52.       Border := $1A;
  53.       Dim := $1B;
  54.       Reverse := $21;
  55.      end;
  56.     end;
  57.     TextAttr := Dim;
  58.   end;
  59.  
  60.   {$F+}
  61.   function GetKey : Word;
  62.     {-Routine to return next keystroke}
  63.   var
  64.     ChWord : Word;
  65.   begin
  66.     ChWord := ReadKeyWord;
  67.     {check for Alt-U}
  68.     if ChWord = $1600 then begin
  69.       {translate to ESC and set flag to disable the TSR}
  70.       ChWord := $001B;
  71.       Disable := True;
  72.     end;
  73.     GetKey := ChWord;
  74.   end;
  75.   {$F-}
  76.  
  77.   function GetFileName(var FName : String64) : Boolean;
  78.     {-Prompt for a file name}
  79.   const
  80.     Prompt = 'File to write: ';
  81.   var
  82.     Escaped : Boolean;
  83.   begin
  84.     ForceUpper := True;
  85.     EditSize := ScreenWidth-(Length(Prompt)+4);
  86.     ReadString(Prompt, 2, 3, 64, Bright, Dim, Dim, Escaped, FName);
  87.  
  88.     GetFileName := (Length(FName) <> 0) and not Escaped;
  89.   end;
  90.  
  91.   procedure ErrorMessage(Msg : String);
  92.     {-Display an error message and wait for a keypress}
  93.   const
  94.     PressAnyKey = '. Press any key...';
  95.   begin
  96.     if Length(Msg)+Length(PressAnyKey)+4 <= ScreenWidth then
  97.       Msg := Msg+PressAnyKey;
  98.     FastWrite(Pad(Msg, ScreenWidth-4), 2, 3, Bright);
  99.     if ReadKeyWord = 0 then {};
  100.   end;
  101.  
  102.   {$F+}
  103.   procedure PopupEntryPoint(var Regs : Registers);
  104.     {-This is the entry point for the popup}
  105.   type
  106.     VideoWord =
  107.       record
  108.         Ch : Char; Attr : Byte;
  109.       end;
  110.     ScreenType = array[1..50, 1..80] of VideoWord; {50 rows * 80 columns}
  111.   const
  112.     FName : String64 = '';
  113.   var
  114.     ScreenPtr : ^ScreenType;
  115.     ScreenBufPtr : ^ScreenType absolute MainBufPtr;
  116.     SaveXY, SaveSL : Word;   {for storing cursor position and shape}
  117.     CurRow, CurCol,          {current cursor coordinates}
  118.     StartRow, StartCol,      {start of marked block}
  119.     Row, Cols, I : Byte;
  120.     ChWord : Word;
  121.     Ch : Char absolute ChWord;
  122.     Highlight,               {true if initial point has been marked}
  123.     WinSelected : Boolean;   {true after window was selected}
  124.     NewRow : Word;
  125.  
  126.     procedure MarkBlock(TopRow, BotRow, LeftCol, RightCol : Byte);
  127.       {-Mark the specified block}
  128.     var
  129.       Row, Cols : Word;
  130.     begin
  131.       Cols := Succ(RightCol-LeftCol);
  132.       for Row := TopRow to BotRow do
  133.         ChangeAttribute(Cols, Row, LeftCol, Reverse);
  134.     end;
  135.  
  136.     procedure RestoreBlock(TopRow, BotRow, LeftCol, RightCol : Byte);
  137.       {-Unmark the specified block}
  138.     var
  139.       Row, Cols : Word;
  140.     begin
  141.       Cols := Succ(RightCol-LeftCol);
  142.       for Row := TopRow to BotRow do
  143.         MoveScreen(ScreenBufPtr^[Row, LeftCol], ScreenPtr^[Row, LeftCol], Cols);
  144.     end;
  145.  
  146.     procedure IncRow(N : Word);
  147.       {-Move the cursor N rows down}
  148.     var
  149.       I : Word;
  150.     begin
  151.       for I := 1 to N do begin
  152.         {make sure we don't go too far down}
  153.         if CurRow = ScreenHeight then
  154.           Exit;
  155.  
  156.         Inc(CurRow);
  157.         if Highlight then
  158.           if (CurRow > StartRow) and (CurCol >= StartCol) then
  159.             MarkBlock(Pred(CurRow), CurRow, StartCol, CurCol);
  160.       end;
  161.     end;
  162.  
  163.     procedure DecRow(N : Integer);
  164.       {-Move the cursor N rows up}
  165.     var
  166.       OldRow, I : Word;
  167.     begin
  168.       for I := 1 to N do begin
  169.         {make sure we don't go too far up}
  170.         if CurRow = 1 then
  171.           Exit;
  172.  
  173.         OldRow := CurRow;
  174.         Dec(CurRow);
  175.         if Highlight then
  176.           if (OldRow > StartRow) and (CurCol >= StartCol) then
  177.             RestoreBlock(OldRow, OldRow, StartCol, CurCol);
  178.       end;
  179.     end;
  180.  
  181.     procedure IncCol(N : Word);
  182.       {-Move the cursor N columns to the right}
  183.     var
  184.       I : Word;
  185.     begin
  186.       for I := 1 to N do begin
  187.         {make sure we don't go too far right}
  188.         if CurCol = ScreenWidth then
  189.           Exit;
  190.  
  191.         Inc(CurCol);
  192.         if Highlight then
  193.           if (CurCol > StartCol) and (CurCol >= StartCol) then
  194.             MarkBlock(StartRow, CurRow, Pred(CurCol), CurCol);
  195.       end;
  196.     end;
  197.  
  198.     procedure DecCol(N : Word);
  199.       {-Move the cursor N columns to the left}
  200.     var
  201.       OldCol, I : Word;
  202.     begin
  203.       for I := 1 to N do begin
  204.         {make sure we don't go too far left}
  205.         if CurCol = 1 then
  206.           Exit;
  207.  
  208.         OldCol := CurCol;
  209.         Dec(CurCol);
  210.         if Highlight then
  211.           if (OldCol > StartCol) and (CurCol >= StartCol) then
  212.             RestoreBlock(StartRow, CurRow, OldCol, OldCol);
  213.       end;
  214.     end;
  215.  
  216.     procedure TabRight;
  217.       {-Moves the cursor to the next tab stop}
  218.     var
  219.       NewCol : Word;
  220.     begin
  221.       if CurCol < ScreenWidth then begin
  222.         NewCol := Succ(Succ(Pred(CurCol) shr 3) shl 3); {shr 3 = div 8}
  223.         IncCol(NewCol-CurCol);
  224.       end;
  225.     end;
  226.  
  227.     procedure TabLeft;
  228.       {-Moves the cursor back to the last tab stop}
  229.     var
  230.       NewCol : Word;
  231.     begin
  232.       NewCol := CurCol;
  233.       if (Pred(NewCol) and 7) = 0 then
  234.         if NewCol > 8 then
  235.           Dec(NewCol, 8)
  236.         else
  237.           NewCol := 1
  238.       else
  239.         NewCol := Succ(Pred(NewCol) and $F8);
  240.       DecCol(CurCol-NewCol);
  241.     end;
  242.  
  243.     procedure DrawOurWindow;
  244.       {-Draw our window}
  245.     begin
  246.       Window(1, 1, ScreenWidth, 3);
  247.       ClrScr;
  248.       FrameWindow(1, 1, ScreenWidth, 3, Border, Reverse, ' PSCREEN 5.02 ');
  249.     end;
  250.  
  251.     procedure RestoreWholeScreen;
  252.       {-Restore the whole screen}
  253.     begin
  254.       RestoreWindow(1, 1, ScreenWidth, ScreenHeight, False, MainBufPtr);
  255.     end;
  256.  
  257.   begin
  258.     {re-initialize CRT}
  259.     ReInitCrt;
  260.  
  261.     if InTextMode and (ScreenWidth <= MaxCols) and (ScreenHeight <= MaxRows) then begin
  262.       {initialize screen stuff}
  263.       SetAttributes;
  264.       GetCursorState(SaveXY, SaveSL);
  265.  
  266.       {save the screen}
  267.       if SaveWindow(1, 1, ScreenWidth, ScreenHeight, False, MainBufPtr) then
  268.         {can't fail};
  269.       ScreenPtr := Ptr(VideoSegment, 0);
  270.  
  271.       WinSelected := False;  {Window is not selected now}
  272.       Highlight := False;
  273.       CurCol := WherexAbs;   {Get cursor pos to start with}
  274.       CurRow := WhereyAbs;
  275.       BlockCursor;
  276.  
  277.       repeat
  278.         {Move to position}
  279.         GotoxyAbs(CurCol, CurRow);
  280.         ChWord := GetKey;
  281.         if Ch = #0 then
  282.           case Hi(ChWord) of
  283.             72 :             {Up}
  284.               DecRow(1);
  285.             80 :             {Down}
  286.               IncRow(1);
  287.             75 :             {Left}
  288.               DecCol(1);
  289.             77 :             {Right}
  290.               IncCol(1);
  291.             115,             {^Left}
  292.             15 :             {Shift-Tab}
  293.               TabLeft;
  294.             116 :            {^Right}
  295.               TabRight;
  296.             119,             {^Home}
  297.             132 :            {^PgUp}
  298.               DecRow(Pred(ScreenHeight));
  299.             117,             {^End}
  300.             118 :            {^PgDn}
  301.               IncRow(Pred(ScreenHeight));
  302.             73 :             {PgUp}
  303.               begin
  304.                 NewRow := CurRow;
  305.                 if (CurRow mod 5) = 0 then
  306.                   Dec(NewRow, 5)
  307.                 else
  308.                   Dec(NewRow, CurRow mod 5);
  309.                 DecRow(CurRow-NewRow);
  310.               end;
  311.             81 :             {PgDn}
  312.               begin
  313.                 NewRow := Succ(CurRow div 5)*5;
  314.                 IncRow(NewRow-CurRow);
  315.               end;
  316.             71 :             {Home}
  317.               DecCol(ScreenWidth);
  318.             79 :             {End}
  319.               IncCol(ScreenWidth);
  320.           end
  321.         else
  322.           case Ch of
  323.             ^H :             {BkSp}
  324.               DecCol(1);
  325.             ' ' :            {space}
  326.               IncCol(1);
  327.             ^I :             {Tab}
  328.               TabRight;
  329.             #27 :            {Esc}
  330.               begin
  331.                 Highlight := False;
  332.                 WinSelected := True;
  333.               end;
  334.             ^M :             {Enter}
  335.               if not Highlight then begin
  336.                 {save starting point}
  337.                 StartCol := CurCol;
  338.                 StartRow := CurRow;
  339.                 Highlight := True;
  340.  
  341.                 {change attribute to reverse video at cursor}
  342.                 ChangeAttribute(1, CurRow, CurCol, Reverse);
  343.               end
  344.               else
  345.                 WinSelected := True;
  346.           end;
  347.       until WinSelected;
  348.  
  349.       if Highlight then
  350.         {draw our window}
  351.         DrawOurWindow;
  352.  
  353.       {get name of file to save screen in}
  354.       if Highlight and GetFileName(FName) then begin
  355.         {restore the screen}
  356.         RestoreWholeScreen;
  357.  
  358.         {save the packed window}
  359.         PWP := PackWindow(StartCol, StartRow, CurCol, CurRow);
  360.         if PWP <> nil then begin
  361.           {try to write the packed window to disk}
  362.           WritePackedWindow(PWP, FName);
  363.           if CrtError <> 0 then begin
  364.             DrawOurWindow;
  365.             ErrorMessage('Error while writing packed window to disk');
  366.             RestoreWholeScreen;
  367.           end;
  368.  
  369.           {dispose of the packed window}
  370.           DisposePackedWindow(PWP);
  371.         end;
  372.       end
  373.       else begin
  374.         {restore the screen}
  375.         RestoreWholeScreen;
  376.  
  377.         {try to disable TSR if requested}
  378.         if Disable then
  379.           if not DisableTSR then begin
  380.             Disable := False;
  381.             Write(^G);
  382.           end;
  383.       end;
  384.  
  385.       {restore cursor state}
  386.       RestoreCursorState(SaveXY, SaveSL);
  387.     end
  388.     else
  389.       Write(^G);
  390.   end;
  391.   {$F-}
  392.  
  393.   procedure Abort(Msg : string);
  394.     {-Display an error message and halt}
  395.   begin
  396.     WriteLn(Msg);
  397.     Halt(1);
  398.   end;
  399.  
  400.   procedure Initialize;
  401.     {-Initialize and check for command line parameters}
  402.   var
  403.     PWP : PackedWindowPtr;
  404.     FName : String64;
  405.   begin
  406.     {initialize}
  407.     EditKeyPtr := @GetKey;
  408.  
  409.     {resident mode if no parameters specified}
  410.     if ParamCount = 0 then
  411.       Exit;
  412.  
  413.     {get the filename and display it}
  414.     FName := ParamStr(1);
  415.     PWP := ReadPackedWindow(FName);
  416.     if PWP = nil then
  417.       Abort('Error reading '+FName);
  418.     DispPackedWindow(PWP);
  419.     Halt;
  420.   end;
  421.  
  422. begin
  423.   {see if there is a file to display}
  424.   Initialize;
  425.  
  426.   {signon message}
  427.   HighVideo;
  428.   WriteLn(^M^J, ProgName, ^M^J, Copyright, ^M^J);
  429.   LowVideo;
  430.  
  431.   {check to see if SideKick is loaded}
  432.   if SideKickLoaded then
  433.     Abort('Can''t be loaded after SideKick!');
  434.  
  435.   {check to see if we're already installed}
  436.   if ModuleInstalled(ModuleName) then
  437.     Abort('PSCREEN is already loaded. Aborting...');
  438.  
  439.   {install the module}
  440.   InstallModule(ModuleName, nil);
  441.  
  442.   {go resident}
  443.   if DefinePop(OurHotKey, @PopupEntryPoint, Ptr(SSeg, SPtr), True) then begin
  444.     WriteLn('PSCREEN loaded. Press Ctrl-LeftShift-P to activate.');
  445.  
  446.     {Enable popups}
  447.     PopupsOn;
  448.  
  449.     {$IFDEF Ver40}
  450.     {restore INT $1B, captured by TPCRT}
  451.     SetIntVec($1B, SaveInt1B);
  452.     {$ENDIF}
  453.  
  454.     {calculate amount of heap space to set aside}
  455.     case EnhancedDisplay of
  456.       EGA : MaxRows := 43;
  457.       VGA : MaxRows := 50;
  458.       else MaxRows := 25;
  459.     end;
  460.     if ScreenWidth > 80 then
  461.       MaxCols := ScreenWidth
  462.     else
  463.       MaxCols := 80;
  464.     MaxParas := (MaxRows*MaxCols*2)+(SizeOf(PackedWindow)-SizeOf(PackedScreen));
  465.     MaxParas := (MaxParas+$F) div 16;
  466.  
  467.     {allocate main screen buffer}
  468.     GetMem(MainBufPtr, MaxRows*MaxCols*2);
  469.  
  470.     {terminate and stay resident}
  471.     if not TerminateAndStayResident(ParagraphsToKeep+MaxParas, 0) then {} ;
  472.   end;
  473.  
  474.   {if we get here we failed}
  475.   Abort(LoadError);
  476. end.
  477.