home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / pascal / pascalm / pascalm.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-05-01  |  68.2 KB  |  2,176 lines

  1. {$S40,P+,T+}
  2. PROGRAM Pas_Main ;
  3.  
  4. (* Program:     PASCALM.PAS
  5.    By:          Jinfu Chen, based on OSS' PASCAL 1.x source code
  6.    Rev:         0.93, 1/1/88, Enhancements added 4/88 by Phillip R. Poulos
  7. *)
  8.  
  9. (*$I auxsubs.pas*)
  10.  
  11.   CONST
  12.     {$I gemconst.pas}
  13.     {$I pascalm.i}          (* resource file definition *)
  14.     max_option = 30 ;       (* Maximum number of options in one dialog *)
  15.     chunk = 10240 ;         (* size to be copy at one time *)
  16.     HIDE = TRUE;            (* just name them for the ease of reading *)
  17.     NOHIDE = FALSE;
  18.     GEM_O = 1 ;
  19.     TOS_O = 2 ;
  20.     TTP_O = 3 ;
  21.     ACC_O = 4 ;
  22.     console=2 ;
  23.     bell=7 ;
  24.     BEG_Mctrl = 3 ;     {Mouse Control constants to try to stop MENU foulups}
  25.     END_Mctrl = 2 ;
  26.     LA_Intin  = 8 ;
  27.  
  28.   TYPE
  29.     opt_range = 1..max_option ;
  30.     opt_array = PACKED ARRAY [ opt_range ] OF Boolean ;
  31.     environment = C_String ;
  32.     env_ptr = ^environment ;
  33.     buf_type = PACKED ARRAY [1..chunk] OF BYTE ;
  34.     drive_array = PACKED ARRAY[1..4] OF Long_Integer ;
  35.     time_buf = ARRAY[1..2] OF Integer ;
  36.     C_Path_Type = PACKED ARRAY [1..80] OF CHAR ;
  37.     DTA = PACKED RECORD                 {DTA record format for GEMDOS stuff}
  38.         rsvd   : PACKED ARRAY[0..19] OF BYTE ;
  39.         rsvd2  : BYTE ;
  40.         attrib : BYTE ;
  41.         time   : Integer ;
  42.         date   : Integer ;
  43.         size   : Long_Integer ;
  44.         name   : C_Path_Type ;
  45.       END ;
  46.     Object = RECORD             {GEM Object record definition}
  47.         ob_next    : Integer ;
  48.         ob_head    : Integer ;
  49.         ob_tail    : Integer ;
  50.         ob_type    : Integer ;
  51.         ob_flags   : Integer ;
  52.         ob_state   : Integer ;
  53.         ob_spec    : Long_Integer ;
  54.         ob_x       : Integer ;
  55.         ob_y       : Integer ;
  56.         ob_width   : Integer ;
  57.         ob_height  : Integer ;
  58.       END ;
  59.     Tree = ARRAY[0..100] OF Object ; {Yes, a Tree is an array of OBJECTS}
  60.     Dialog_Ptr = ^Tree ; {The correct and USEFUL redefinition of a Dialog Ptr}
  61.     Average_Array = ARRAY[0..500] of Integer;
  62.     Aver_Array_Ptr = ^AVERAGE_ARRAY;
  63.          
  64.     {$I gemtype.pas}
  65.  
  66.   VAR
  67.     envp : env_ptr ;
  68.     rez  : integer ;                (* screen resolution *)
  69.     menu : Menu_Ptr ;
  70.     info_x,
  71.     info_y,
  72.     info_w,
  73.     info_h,
  74.     dummy : integer ;
  75.     for_gem : Integer ;        (* 1 for gem, 2 for tos, 3 for acc *)
  76.     cmp_opts : opt_array ;
  77.     Prog_DTA : DTA ;
  78.     bad_res,
  79.     temp_path,
  80.     backup_path,
  81.     addl_files,
  82.     addl_libs : Str255 ;
  83.     work_path,                  (* path for FILE menu *)
  84.     file_path1,                  (* path for SPECIALS menu *)
  85.     file_path2,                  (* path for SPECIALS menu *)
  86.     def_path,
  87.     compiler_name,
  88.     linker_name,
  89.     editor_name,
  90.     paslib_name,
  91.     pasgem_name,
  92.     printer_name,
  93.     src_name,                   (* source filename for COPY *)
  94.     des_name,                   (* destination filename for COPY *)
  95.     cmp_name,
  96.     link_name,
  97.     edit_name,                  {Notice separate paths for EDIT file}
  98.     compile_name,               {  and COMPILE file}
  99.     run_name : Path_Name ;
  100.     info_dial : Dialog_Ptr ;
  101.     Intin : Aver_Array_Ptr;
  102.  
  103.     
  104.   {$I gemsubs.pas}
  105.   
  106. FUNCTION Ptr( where : long_integer ) : Aver_Array_Ptr ;
  107.   External;
  108.  
  109.  
  110. PROCEDURE Obj_Size( dial : dialog_ptr ; Root : integer ;
  111.   VAR x, y, w, h: integer ) ;   {Returns an OBJECT's size; however boxes}
  112.   EXTERNAL ;                    {are frequently sized too SMALL by GEM}
  113.  
  114.  
  115. PROCEDURE Obj_Draw( dial : dialog_ptr ; start,depth,x,y,w,h:integer) ;
  116.   EXTERNAL;                {Needed to draw only a part of a Object Tree}
  117.  
  118.  
  119. PROCEDURE FORM_DIAL(flag,x_sm,y_sm,w_sm,h_sm,x_lg,y_lg,w_lg,
  120.                    h_lg:integer) ;
  121.   EXTERNAL;
  122.  
  123.  
  124. PROCEDURE Grow_Shrink( cmd, small_x, small_y, small_w, small_h,
  125.                         big_x, big_y, big_w, big_h : integer ) ;
  126.   VAR
  127.     int_in   : Int_In_Parms ;
  128.     int_out  : Int_Out_Parms ;
  129.     addr_in  : Addr_In_Parms ;
  130.     addr_out : Addr_Out_Parms ;
  131.   BEGIN
  132.     int_in[0] := small_x ;
  133.     int_in[1] := small_y ;
  134.     int_in[2] := small_w ;
  135.     int_in[3] := small_h ;
  136.     int_in[4] := big_x ;
  137.     int_in[5] := big_y ;
  138.     int_in[6] := big_w ;
  139.     int_in[7] := big_h ;
  140.     AES_Call( cmd, int_in, int_out, addr_in, addr_out ) ;
  141.     END ;
  142.  
  143.  
  144. PROCEDURE Grow_Box( s_x, s_y, s_w, s_h,
  145.                       b_x, b_y, b_w, b_h : integer ) ;
  146.   BEGIN
  147.       Grow_Shrink( 73, s_x, s_y, s_w, s_h, b_x, b_y, b_w, b_h ) ;
  148.     END ;
  149.  
  150.  
  151. PROCEDURE Shrink_Box( big_x, big_y, big_w, big_h,
  152.                         small_x, small_y, small_w, small_h : integer ) ;
  153.   BEGIN
  154.     Grow_Shrink( 74, small_x, small_y, small_w, small_h,
  155.               big_x, big_y, big_w, big_h ) ;
  156.   END ;
  157.  
  158.  
  159. PROCEDURE WIND_Update ( ctrl : Integer ) ; {Use this call for MOUSE control}
  160. VAR
  161.   int_in   : Int_In_Parms ;
  162.   int_out  : Int_Out_Parms ;
  163.   addr_in  : Addr_In_Parms ;
  164.   addr_out : Addr_Out_Parms ;
  165. BEGIN
  166.   int_in[0] := ctrl ;
  167.   AES_Call( 107, int_in, int_out, addr_in, addr_out ) ;
  168. END ;
  169.  
  170.  
  171. {  Returns address of LINEA variables  }
  172. FUNCTION Linea_init : Long_integer;
  173.   External;
  174.  
  175.  
  176. {  LineA Show Mouse Routine  }
  177. Procedure Linea_Showms;
  178.   External;
  179.  
  180.  
  181. FUNCTION Dsetdrv( drive : INTEGER ) : Long_INTEGER ; (* Set Default Drive *)
  182.   GEMDOS($0E) ;
  183.  
  184.  
  185. FUNCTION Dgetdrv : integer ; {Get Default Drive}
  186.   GEMDOS( $19 ) ;
  187.  
  188. FUNCTION FCreate( VAR fname : C_Path_Type ; mode : INTEGER ) : INTEGER ;
  189.   GEMDOS( $3C ) ;
  190.  
  191. PROCEDURE Dfree( VAR buf : DRIVE_ARRAY ; driveno : INTEGER ) ;
  192.   GEMDOS($36) ;
  193. (* Get Drive Free Space *)
  194. (* Some Information :
  195.   buf[1] : number of free clusters ;
  196.   buf[2] : total number of clusters ;
  197.   buf[3] : sector size in bytes ;
  198.   buf[4] : cluster size in bytes.
  199. *)
  200.  
  201. FUNCTION Mkdir( VAR Folder : C_Path_Type) : Integer ;
  202.   GEMDOS( $39 ) ;               {Make a new directory or folder}
  203.  
  204. FUNCTION DDelete( VAR pathname : C_Path_Type ) : INTEGER ;
  205.   GEMDOS( $3A ) ;
  206. (* Delete Directory *)
  207.  
  208. FUNCTION FOpen( VAR fname : C_Path_Type ; mode : INTEGER ) : INTEGER ;
  209.   GEMDOS( $3D ) ;
  210.  
  211. PROCEDURE FClose( fhandle : INTEGER ) ;
  212.   GEMDOS( $3E ) ;
  213.  
  214. FUNCTION FRead( fhandle : INTEGER ; n_bytes : Long_INTEGER ;
  215.                  VAR buf : buf_type ) : Long_Integer ;
  216.   GEMDOS( $3F ) ;
  217.  
  218. FUNCTION FWrite( fhandle : INTEGER ; n_bytes : Long_INTEGER ;
  219.                  VAR buf : buf_type ) : Long_Integer ;
  220.   GEMDOS( $40 ) ;
  221.  
  222. FUNCTION FDelete( VAR fname : C_Path_Type ) : INTEGER ;
  223.   GEMDOS( $41 ) ;
  224. (* Delete File *)
  225.  
  226. PROCEDURE Dgetpath( VAR path_buf : C_Path_Type ; drive : integer ) ;
  227.   GEMDOS( $47 ) ;       {Get current file path}
  228.   
  229. FUNCTION Dsetpath( VAR path_buf : C_Path_Type ) : Integer ;
  230.   GEMDOS( $3B ) ;       {Set new default path}
  231.  
  232. FUNCTION FRename( zero : INTEGER; VAR oldname,
  233.                   newname : C_Path_TYPE ) : INTEGER ;
  234.   GEMDOS( $56 ) ;
  235. (* Rename File *)
  236.  
  237. FUNCTION SFirst( VAR fn : C_Path_Type ; attribute : Integer ) : Integer ;
  238.   GEMDOS( $4E ) ;       {Get first file name match in current directory}
  239.  
  240. FUNCTION SNext : Integer ; {Get NEXT file name match in current path}
  241.   GEMDOS( $4F ) ;  
  242.   
  243. FUNCTION Chmod( VAR Fname : C_Path_Type ; mode, attribute : Integer ) : Integer ;
  244.   GEMDOS( $43 ) ;       {Change attributes of file - used to make write}
  245.                         {enabled}
  246. PROCEDURE SetDTA( VAR DTA_Buf : DTA ) ;
  247.   GEMDOS( $1A ) ;       {Set up our own DTA area for GEMDOS to use}
  248.   
  249. PROCEDURE FDaTime( VAR buf : time_buf ; handle, flag : Integer ) ;
  250.   GEMDOS( $57 ) ;       {Get or Set File Date/Time Stamp}
  251.  
  252. FUNCTION get_rez : integer ;
  253.   XBIOS( 4 ) ;
  254.  
  255. PROCEDURE bconin( dev : integer ) ;     (* Really a function! *)
  256.   BIOS( 2 ) ;
  257.  
  258. PROCEDURE bconout( dev, c : integer ) ;
  259.   BIOS( 3 ) ;
  260.  
  261.  
  262. PROCEDURE P_To_CPath( VAR P_Path : Path_Name ; VAR C_Path : C_Path_Type ) ;
  263. (* convert Pascal string to C string, the built-in routines only work for
  264.    long string *)
  265. VAR
  266.   len,
  267.   i     : INTEGER;
  268. BEGIN
  269.   len := Length( p_path ) ;
  270.   FOR i := 1 TO len DO c_path[i] := p_path[i] ;
  271.   c_path[ len + 1 ] := chr(0) ;
  272. END ;
  273.  
  274.  
  275. PROCEDURE C_To_PPath( VAR C_Path : C_Path_Type ; VAR P_Path : Path_Name ) ;
  276. (* convert C string to Pascal string *)
  277. VAR
  278.   i     : INTEGER;
  279. BEGIN
  280.   i := 1 ;
  281.   While (C_Path[i] <> CHR(0)) AND (C_Path[i] <> ' ') AND ( i <= 80 ) DO BEGIN
  282.     P_Path[i] := C_Path[i] ;
  283.     i := i + 1 ;
  284.   END ;
  285.   P_Path[0] := Chr( i - 1 ) ;
  286. END ;
  287.  
  288.  
  289. PROCEDURE IO_Error( err : Integer ) ;
  290. {Display I/O error in alert box}
  291. VAR err_str : Str255 ;
  292.     c1 : Integer ;
  293. BEGIN
  294.   IF err <> 0 THEN
  295.     BEGIN
  296.       CASE err OF
  297.         -1  : err_str := 'TOS system error' ;
  298.         -2  : err_str := 'Drive not ready' ;
  299.         -3  : err_str := 'Unknown error' ;
  300.         -4  : err_str := 'CRC error' ;
  301.         -5  : err_str := 'Bad request' ;
  302.         -6  : err_str := 'Drive seek error' ;
  303.         -7  : err_str := 'Unknown media' ;
  304.         -8  : err_str := 'Drive sector not found' ;
  305.         -9  : err_str := 'No paper' ;
  306.         -10 : err_str := 'Drive write fault' ;
  307.         -11 : err_str := 'Drive read fault' ;
  308.         -12 : err_str := 'General error' ;
  309.         -13 : err_str := 'Drive write protect' ;
  310.         -14 : err_str := 'Drive media change' ;
  311.         -15 : err_str := 'Unknown device' ;
  312.         -16 : err_str := 'Bad sectors on format' ;
  313.         -17 : err_str := 'Disk change' ;
  314.         -18 : err_str := 'Disk Full' ;
  315.         -32 : err_str := 'Invalid function number' ;
  316.         -33 : err_str := 'File not found' ;
  317.         -34 : err_str := 'Path not found' ;
  318.         -35 : err_str := 'Too many open files' ;
  319.         -36 : err_str := 'Access not possible' ;
  320.         -37 : err_str := 'Cannot copy, rename, or|move file to self' ;
  321.         -38 : err_str := 'Cannot rename or move|to/from null string' ;
  322.         -39 : err_str := 'Insufficient memory' ;
  323.         -40 : err_str := 'Invalid memory block address' ;
  324.         -46 : err_str := 'Invalid drive' ;
  325.         -49 : err_str := 'No more files' ;
  326.         -64 : err_str := 'Range error' ;
  327.         -65 : err_str := 'Internal error' ;
  328.         -66 : err_str := 'Invalid program load format' ;
  329.         -67 : err_str := 'Setblock failure ' ;
  330.         OTHERWISE : WriteV( err_str, 'I/O error #', err ) ;
  331.       END ; 
  332.       err_str := Concat( '[3][ |', err_str, '][ OK ]' ) ;
  333.       bconout( console, bell ) ;
  334.       c1 := Do_Alert( err_str, 1 ) ;
  335.     END ;
  336. END ;
  337.  
  338.  
  339. PROCEDURE Redraw_Screen ;
  340. {Redraw screen by forcing a redraw message to GEM}
  341. VAR
  342.   x, y, w, h : integer;
  343. BEGIN
  344.   Work_Rect( 0, x, y, w, h ) ;
  345.   Form_Dial( 3, 0, 0, 0, 0, x, y, w, h ) ;  (* a dirty and quick way *)
  346. END ;
  347.  
  348.  
  349. FUNCTION Is_Gem_Name( fname : Path_Name ) : boolean ;
  350. (* check if the program is a GEM program *)
  351. VAR
  352.   i : integer ;
  353. BEGIN
  354.   Is_Gem_Name := false ;
  355.   IF length( fname ) > 3 THEN  BEGIN
  356.     i := length( fname ) - 3 ;
  357.     IF ( fname[i]='.') AND (fname[i+1]='P') AND (fname[i+2]='R')
  358.       AND (fname[i+3]='G') THEN
  359.         Is_Gem_name := true ;
  360.   END
  361. END ;
  362.  
  363.  
  364. FUNCTION Is_TTP_Name( fname : Path_Name ) : boolean ;
  365. (* check if the program is a TTP program *)
  366. VAR
  367.   i : integer ;
  368. BEGIN
  369.   Is_TTP_Name := false ;
  370.   IF length( fname ) > 3 THEN  BEGIN
  371.     i := length( fname ) - 3 ;
  372.     IF ( fname[i]='.') AND (fname[i+1]='T') AND (fname[i+2]='T')
  373.       AND (fname[i+3]='P') THEN
  374.         Is_TTP_name := true ;
  375.   END
  376. END ;
  377.  
  378.  
  379. PROCEDURE Strip_Filename( VAR Pth, fn : Path_Name ) ;
  380. {Strip_Filename - Remove the File Name/Extension from a Path_Name variable.}
  381. {also process input path to remove redundant characters}
  382.   VAR
  383.     i : integer ;
  384.     done : boolean ;
  385.   BEGIN
  386.     i := Length( pth ) ;
  387.     fn := '' ;
  388.     IF i=0 THEN done := TRUE
  389.     ELSE done := FALSE ;
  390.     WHILE NOT done DO
  391.       BEGIN
  392.         IF i < 1 THEN
  393.           BEGIN
  394.             fn := pth ;
  395.             pth := '' ;
  396.             done := true ;
  397.           END  
  398.         ELSE IF pth[i] = '\' THEN
  399.           BEGIN
  400.             IF (pth[i-1]='\') AND (i>1) THEN
  401.               BEGIN
  402.                 Delete( pth, i, 1 ) ;
  403.                 i := i - 1 ;
  404.               END
  405.             ELSE
  406.               BEGIN    
  407.                 fn := Copy( pth, i+1, length(pth)-i ) ;
  408.                 pth[0] := chr(i) ;
  409.                 done := true ;
  410.               END ;  
  411.           END  
  412.         ELSE IF pth[i] = ':' THEN
  413.           BEGIN
  414.             fn := Copy( pth, i+1, length(pth)-i ) ;
  415.             pth[0] := chr(i) ;
  416.             done := true ;
  417.           END  
  418.         ELSE
  419.           i := i - 1 ;
  420.       END ;
  421.     i := Length(pth) ;
  422.     IF i>1 THEN
  423.       REPEAT
  424.         IF (pth[i]='\') AND (pth[i-1]='\') THEN Delete( pth, i, 1 ) ;
  425.         i := i - 1 ;
  426.       UNTIL i<2 ;  
  427.   END ;
  428.   
  429.  
  430. PROCEDURE SetupFName( VAR Src, Des : Path_Name ; AddPeriod : Boolean ) ;
  431. {Setup File Name to be displayed in conflict dialog box}  
  432. VAR i,
  433.     j : Integer ;
  434. BEGIN
  435.   des := '            ' ;
  436.   i := 1 ;
  437.   j := 1 ;
  438.   IF Length(Src)>0 THEN
  439.     BEGIN
  440.       REPEAT
  441.         Des[j] := Src[i] ;
  442.         i := i + 1 ;
  443.         j := j + 1 ;
  444.       UNTIL (Src[i]='.') OR (i>Length(Src)) ;
  445.       i := i + 1 ;
  446.       IF i <= Length(Src) THEN
  447.         BEGIN
  448.           IF AddPeriod THEN
  449.             BEGIN
  450.               des[9] := '.' ;
  451.               j := 10 ;
  452.             END  
  453.           ELSE j := 9 ;
  454.           REPEAT
  455.             Des[j] := Src[i] ;
  456.             i := i + 1 ;
  457.             j := j + 1 ;
  458.           UNTIL i>Length(Src) ;
  459.         END ;
  460.       IF j>8 THEN des[0] := Chr(j-1) ;  
  461.     END ;
  462. END ;          
  463.  
  464.  
  465. FUNCTION Get_CMD( fname : Path_Name; VAR  cmd_line : Str255 ) : BOOLEAN ;
  466. (* get the command line for TTP program, the box looks exactly the same as
  467.    the one in DESKTOP *)
  468. VAR
  469.   i : integer ;
  470.   btn : Integer ;
  471.   t_box : Dialog_Ptr ;
  472.   name : Path_Name ;
  473. BEGIN
  474.   cmd_line[0] := chr(0) ;              (* zero length the cmd_line *)
  475.   Get_CMD := TRUE ;
  476.   Find_Dialog( TTPBOX, t_box ) ;
  477.   Center_Dialog( t_box ) ;
  478.   Strip_Filename( fname, name ) ;
  479.   fname := name ;
  480.   SetupFName( fname, name, TRUE ) ;
  481.   Set_DText( t_box, TTPNAME, name, System_Font, TE_LEFT ) ;
  482.   Set_DText( t_box, CMDLINE, cmd_line, System_Font, TE_LEFT ) ;
  483.   btn := Do_Dialog( t_box, CMDLINE ) ;
  484.   Obj_SetState( t_box, btn, NORMAL, TRUE ) ;
  485.   IF btn = TTPCAN THEN
  486.     Get_CMD := FALSE ;
  487.   Get_DEdit( t_box, CMDLINE, cmd_line ) ;
  488.   End_Dialog( t_box ) ;
  489. END ;
  490.  
  491.  
  492. PROCEDURE Wait(waittime : Long_Integer);
  493. (* just wait for  n seconds. Note that TOS clock is in 2 second interval *)
  494. VAR
  495.   starttime : Long_Integer;
  496. BEGIN
  497.   starttime := Clock;
  498.   WHILE ((Clock - starttime) < waittime ) DO
  499.     ;
  500. END;
  501.  
  502.  
  503. {$P-}
  504.  
  505. PROCEDURE info_msg( msg : String ) ;
  506. {Display title in BOX over File Selector Box}
  507. BEGIN
  508.   Find_Dialog(LOCATION, info_dial);
  509.   Center_Dialog( info_dial ) ;
  510.   Obj_Size( info_dial, ROOT, info_x, info_y, info_w, info_h ) ;
  511.   info_y := 12 * rez ;
  512.   info_dial^[0].ob_y := info_y ;   {Change y position of parent object after}
  513.   info_x := info_x - 5 ;           {object centered, then widen out clip}
  514.   info_y := info_y - 5 ;           {rectangle before display}
  515.   info_w := info_w + 20 ;
  516.   info_h := info_h + 20 ;
  517.   Set_DText( info_dial, INFONAME, msg, System_Font, TE_CENTER ) ;
  518.   Obj_Draw( info_dial, ROOT, max_depth, info_x, info_y, info_w, info_h ) ;
  519. END ;
  520.  
  521. {$P=}
  522.  
  523.  
  524. PROCEDURE EraseInfo ;
  525. BEGIN
  526.   Form_Dial( 3, 0, 0, 0, 0, info_x, info_y, info_w, info_h ) ;
  527. END ;  
  528.  
  529.  
  530. PROCEDURE formdo(index : INTEGER; hide : BOOLEAN) ;
  531. {Displays beginning information about program}
  532. VAR
  533.   x, y, w, h    : Integer ;
  534.   dia_obj       : Dialog_Ptr;
  535. BEGIN (* formdo *)
  536.   Find_Dialog(index, dia_obj);
  537.   Center_Dialog(dia_obj);
  538.   Obj_Size(dia_obj, Root, x, y, w, h ) ;
  539.   x := x - 5 ;
  540.   y := y - 5 ;
  541.   w := w + 10 ;
  542.   h := h + 10 ;
  543.   IF hide THEN
  544.     BEGIN
  545.       Grow_Box( 3*8, 0, 4*8, rez*8, x, y, w, h ) ;
  546.       Show_Dialog(dia_obj, Root);          (* no interaction *)
  547.       Wait(2);                             (* 2 seconds later close down *)
  548.       Form_Dial(3, 0, 0, 0, 0, x, y, w, h);  (* close the box *)
  549.       Shrink_Box( x, y, w, h, 3*8, 0, 4*8, rez*8 ) ;
  550.     END
  551.   ELSE
  552.     BEGIN
  553.       Grow_Box( 3*8, 0, 4*8, rez*8, x, y, w, h ) ;
  554.       dummy := Do_Dialog(dia_obj, 0);      (* no need to hide the buttom *)
  555.       End_Dialog(dia_obj);
  556.       Shrink_Box( x, y, w, h, 3*8, 0, 4*8, rez*8 ) ;
  557.       Obj_Setstate(dia_obj, dummy, NORMAL, FALSE);
  558.     END ;  
  559. END;  (* formdo *)
  560.  
  561.  
  562. PROCEDURE Set_Defaults ;
  563. (* initialize some variables *)
  564.   VAR
  565.     opt : opt_range ;
  566.     path : C_Path_Type ;
  567.     p_path : Path_Name ;
  568.     Table : Long_Integer ;
  569.   BEGIN
  570.     Table := Linea_init;      { Get table of linea variables }
  571.     Intin  := ptr(lpeek(Table + LA_Intin));  { Setup Intin array pointer! }
  572.     FOR opt := 1 TO max_option DO
  573.       IF opt IN [ ERRPAUSE,CHNLINK,DBGOPT,STKOPT,RNGOPT,EDITCOMP ]
  574.         THEN cmp_opts[ opt ] := true ;
  575.     work_path[1] := chr( ord('A') + Dgetdrv ) ;
  576.     work_path[2] := ':' ;
  577.     work_path[0] := chr(2) ;
  578.     Dgetpath( path, 0 ) ;      (* Get default path *) ;
  579.     C_To_PPath(path, p_path);     (* convert C string to Pas string *)
  580.     work_path := concat( work_path, p_path, '\' ) ; (* used by FILE *)
  581.     def_path := work_path ;     {Default path where PASCALM.PRG found}
  582.     file_path1 := concat( work_path, '*.*' ) ; {Used by SPECIALS - "FROM"}
  583.     file_path2 := file_path1 ;  {Used by specials - "TO" pathway}
  584.     editor_name := concat( work_path, 'EDITOR.PRG  ') ;
  585.     compiler_name  := concat( work_path, 'COMPILER.PRG  ' ) ;
  586.     linker_name := concat( work_path, 'LINKER.PRG  ' ) ;
  587.     paslib_name := concat ( work_path, 'PASLIB' ) ;
  588.     pasgem_name := concat ( work_path, 'GEMLIB' ) ;
  589.     printer_name := concat( work_path, 'LISTPAS.PRG' ) ;
  590.     backup_path := work_path ;
  591.     work_path := concat( work_path, '*.PAS' ) ; {Source program path}
  592.     for_gem := GEM_O ;
  593.   END ;
  594.  
  595.  
  596. FUNCTION Chdir( VAR PPath : Path_Name ) : Boolean ;
  597. {Change current default pathway - a necessity in running programs with}
  598. {resource files}
  599. VAR 
  600.    errstr : Str255 ;
  601.    CPath : C_Path_Type ;
  602.    driveID,
  603.    i : Integer ;
  604. BEGIN
  605.   driveID := Ord(PPath[1]) - Ord('A') ;
  606.   IF (ShR(Dsetdrv(driveID),driveID)&$0001)<>1 THEN
  607.     BEGIN
  608.       IO_Error( -15 ) ;
  609.       Chdir := FALSE ;
  610.     END
  611.   ELSE
  612.     BEGIN    
  613.       FOR i := 3 TO Length( PPath ) DO CPath[i-2] := PPath[i] ;
  614.       CPath[i-2] := Chr(0) ;
  615.       i := Dsetpath( CPath ) ;
  616.       IF i=0 THEN Chdir := TRUE
  617.       ELSE
  618.         BEGIN
  619.           IO_Error( i ) ;
  620.           Chdir := FALSE ;
  621.         END ;
  622.     END ;    
  623. END ;    
  624.  
  625.  
  626. FUNCTION Copy_Files( src_file, des_file : Path_Name ) : Boolean ;
  627. (* a generic routine to copy file *)
  628. {The success of the operation is returned}
  629. VAR
  630.   i,
  631.   infile,                      (* file handle for input file *)
  632.   outfile       : INTEGER ;    (* file handle for output file *)
  633.   w_bytes,
  634.   n_bytes       : Long_INTEGER ; (* number of bytes for read/write *)
  635.   write_error   : BOOLEAN ;
  636.   cnvrt_str     : C_Path_Type ;
  637.   buf           : buf_type ;
  638. BEGIN
  639.   IF src_file=des_file THEN
  640.     BEGIN
  641.       IO_Error( -37 ) ;
  642.       Copy_Files := FALSE ;
  643.     END
  644.   ELSE
  645.     BEGIN    
  646.       write_error := FALSE ;
  647.       P_To_CPath(src_file, cnvrt_str) ;      (* convert to C string *)
  648.       Set_Mouse( M_BEE ) ;               (* busy copying file *)
  649.       infile := FOpen( cnvrt_str, 0 ) ;      (* open file to read *)
  650.       IF infile >= 0 THEN
  651.         BEGIN              (* open success *)
  652.           P_To_CPath(des_file, cnvrt_str) ;
  653.           outfile := FCreate( cnvrt_str, 0 ) ; (* open a file regardless *)
  654.           IF outfile >= 0 THEN                 (* of its existence *)
  655.             BEGIN           (* open success *)
  656.               REPEAT
  657.                 n_bytes := FRead( infile, chunk, buf ) ;
  658.                 IF n_bytes > 0 THEN
  659.                   BEGIN        (* we read something *)
  660.                     w_bytes := FWrite( outfile, n_bytes, buf ) ;
  661.                     IF w_bytes <> n_bytes THEN
  662.                       BEGIN
  663.                         write_error := TRUE ;        (* write error *)
  664.                         IF w_bytes < 0 THEN IO_Error( w_bytes )
  665.                         ELSE IO_Error( -18 ) ;   {Presume it is a disk full}
  666.                       END ; (* write *)          {error}
  667.                   END (* read *)
  668.                 ELSE IF n_bytes < 0 THEN
  669.                   BEGIN
  670.                     write_error := TRUE ;
  671.                     IO_Error( n_bytes ) ;
  672.                   END ;    
  673.               UNTIL ((n_bytes = 0) OR write_error ) ;
  674.               FClose( outfile ) ;
  675.             END   (* outfile *)
  676.           ELSE
  677.             BEGIN
  678.               IO_Error( outfile ) ;
  679.               write_error := TRUE ;
  680.             END ;  
  681.           FClose( infile ) ;
  682.         END  (* infile *)
  683.       ELSE
  684.         BEGIN
  685.           IO_Error( infile ) ;
  686.           write_error := TRUE ;
  687.         END ;
  688.       Set_Mouse( M_ARROW ) ;             (* copy is done *)
  689.       Copy_Files := NOT write_error ;
  690.     END ;  
  691. END ;
  692.  
  693.  
  694.  
  695. FUNCTION FileConflict( VAR OldPath, NewPath : Path_Name ;
  696.   copy : Boolean ) : Boolean ;
  697. {This routine will display a File Conflict box if necessary}
  698. {AND give the user a chance to "chicken" out}  
  699. VAR
  700.   tsource,
  701.   destin  : Path_Name ;
  702.   i,
  703.   btn     : Integer ;
  704.   conflict_box : Dialog_Ptr ;
  705.   C_Name  : C_Path_Type ;
  706.   cont : Boolean ;
  707. BEGIN
  708.   SetupFname( des_name, destin, FALSE ) ;
  709.   i := NAMEOK ;
  710.   cont := Chdir( NewPath ) ;
  711.   P_To_CPath( des_name, C_name ) ;
  712.   SetDTA( Prog_DTA ) ;
  713.   IF (SFirst(C_Name,$37)=0) AND cont THEN {Check to see if conflict box needed}
  714.     BEGIN 
  715.       Find_Dialog( NAMECONF, conflict_box ) ;
  716.       Center_Dialog( conflict_box ) ;
  717.       SetupFName( des_name, tsource, TRUE ) ;
  718.       Set_DText( conflict_box, SNAME, tsource, System_Font, TE_LEFT ) ;
  719.       Set_DText( conflict_box, FNAME, destin, System_Font, TE_LEFT ) ;
  720.       IF copy THEN {Display appropriate title for MOVE or COPY}
  721.         Set_DText( conflict_box, CONFTITL, 'NAME CONFICT DURING COPY',
  722.           System_Font, TE_CENTER )
  723.       ELSE      
  724.         Set_DText( conflict_box, CONFTITL, 'NAME CONFICT DURING MOVE',
  725.           System_Font, TE_CENTER ) ;
  726.       i := Do_Dialog( conflict_box, FNAME ) ;
  727.       Get_DEdit( conflict_box, FNAME, temp_path ) ;
  728.       End_Dialog( conflict_box ) ;
  729.       Obj_SetState( conflict_box, i, NORMAL, FALSE ) ;
  730.       IF (Prog_DTA.attrib=$10) AND (temp_path=destin) AND (i=NAMEOK) THEN
  731.         BEGIN
  732.           IO_Error( -36 ) ;
  733.           cont := FALSE
  734.         END  
  735.       ELSE destin := temp_path ;
  736.     END ;
  737.   IF (i=NAMEOK) AND cont THEN
  738.     BEGIN
  739.       des_name := '' ;
  740.       FOR i := 1 TO Length(destin) DO
  741.         BEGIN
  742.           IF destin[i]<>' ' THEN
  743.             BEGIN
  744.               IF i=9 THEN des_name := Concat( des_name, '.' ) ;
  745.               des_name := Concat( des_name, destin[i] ) ;
  746.             END ;
  747.         END ;
  748.       src_name := Concat( OldPath, src_name ) ;
  749.       des_name := Concat( NewPath, des_name ) ;     
  750.     END
  751.   ELSE IF i=NAMECANC THEN cont := FALSE ;  
  752.   FileConflict := NOT cont ;
  753. END ;      
  754.  
  755.  
  756. PROCEDURE Do_Copy;
  757. (* get source and destination names and call copy_file routine *)
  758. VAR
  759.   TempPath,
  760.   NewPath,
  761.   OldPath : Path_Name ;
  762.   dumy    : Boolean ;
  763.  
  764. BEGIN
  765.   Info_Msg('Select File To Be Copied FROM...') ;
  766.   OldPath := src_name ;
  767.   IF Get_In_File( file_path1, OldPath ) AND (length(OldPath) <> 0) THEN
  768.     BEGIN
  769.       EraseInfo ;
  770.       Info_Msg('Select File To Be Copied TO...') ;
  771.       TempPath := OldPath ;
  772.       Strip_Filename( TempPath, NewPath ) ;
  773.       dumy := Get_In_File( file_path2, NewPath ) ;
  774.       EraseInfo ;
  775.       IF dumy AND (Length(NewPath)<>0) THEN 
  776.         BEGIN
  777.           Strip_Filename( OldPath, src_name ) ;
  778.           Strip_Filename( NewPath, des_name ) ;
  779.           IF (Length(src_name)<>0) AND (Length(des_name)<>0) THEN
  780.             BEGIN
  781.               IF NOT FileConflict( OldPath, NewPath, TRUE ) THEN
  782.                 BEGIN
  783.                   dumy := Copy_Files( src_name, des_name ) ;
  784.                   dumy := Chdir( def_path ) ;
  785.                 END ;  
  786.             END  
  787.           ELSE IO_Error( -33 ) ;  
  788.         END ;    
  789.     END  
  790.   ELSE EraseInfo ;
  791.   Menu_Normal( menu, MSPECIAL ) ;
  792. END;
  793.  
  794.  
  795. PROCEDURE Disk_Space ;
  796. (* check free space of a drive *)
  797. VAR
  798.   space_box     : Dialog_Ptr ;
  799.   x, y, w, h,
  800.   btn           : Integer ;
  801.   drive_char,
  802.   byte_used,
  803.   byte_available : Str255 ;
  804.   hold_map,
  805.   temp,
  806.   drive_map     : Long_Integer ;    (* an array with all available drives *)
  807.   drive_id      : Integer ;
  808.   drive_buf     : DRIVE_ARRAY ;
  809.   dumy : Boolean ;
  810. BEGIN
  811.   byte_used := '';
  812.   byte_available := '' ;
  813.   drive_id := Dgetdrv ;                        (* used current drv first *)
  814.   drive_char[1] := CHR(ORD('A') + drive_id) ;  (* convert to char *)
  815.   drive_char[0] := CHR(1) ;                    (* force string length to 1 *)
  816.   hold_map := Dsetdrv(drive_id) ;
  817.   Find_Dialog( DISKSP, space_box ) ;
  818.   Center_Dialog( space_box ) ;
  819.   Obj_Size( space_box, DISKID, x, y, w, h ) ;
  820.   Set_DText( space_box, DISKID, drive_char, System_Font, TE_CENTER ) ;
  821.   Set_DText( space_box, BYTEAVL, '________', System_Font, TE_RIGHT ) ;
  822.   Set_DText( space_box, BYTEUSED,'________', System_Font, TE_RIGHT ) ;
  823.   btn := Do_Dialog( space_box, DISKID ) ;
  824.   LOOP
  825.     WHILE (btn<>DSOKBTN) AND (btn<>DSCANBTN) DO
  826.       BEGIN
  827.         IF btn=DSKLEFT THEN  {Process Left Arrow Presses to decrement Drives}
  828.           BEGIN
  829.             REPEAT
  830.               drive_id := drive_id - 1 ;
  831.               IF drive_id<0 THEN drive_id := 15 ;
  832.             UNTIL (ShR(hold_map,drive_id)&$0001)=1 ;
  833.             drive_char[1] := Chr(Ord('A') + drive_id ) ;
  834.             Set_DText( space_box, DISKID, drive_char, System_Font, TE_CENTER ) ;
  835.             Obj_Draw( space_box, DISKID, DISKID, x, y, w, h ) ;
  836.           END
  837.         ELSE IF btn=DSKRIGHT THEN {Process Right Arrow Presses to advance}
  838.           BEGIN                   {drives}
  839.             REPEAT
  840.               drive_id := drive_id + 1 ;
  841.               IF drive_id>15 THEN drive_id := 0 ;
  842.             UNTIL (ShR(hold_map,drive_id)&$0001)=1 ;
  843.             drive_char[1] := Chr(Ord('A') + drive_id ) ;
  844.             Set_DText( space_box, DISKID, drive_char, System_Font, TE_CENTER ) ;
  845.             Obj_Draw( space_box, DISKID, DISKID, x, y, w, h ) ;
  846.           END ;
  847.         btn := Redo_Dialog( space_box, DISKID ) ;
  848.       END ;
  849.     IF btn=DSOKBTN THEN
  850.       BEGIN  
  851.         Set_Mouse(M_BEE) ;    (* it takes a while for disk-free routine *)
  852.         Get_DEdit( space_box, DISKID, drive_char ) ;
  853.         drive_id := ORD(drive_char[1]) - ORD('A') ;  (* get drive user wants *)
  854.         (* check if the requested drive in system *)
  855.         drive_map := ShR( Dsetdrv(drive_id), drive_id ) & $0001; (* check bit *)
  856.         IF drive_map = 1 THEN
  857.           BEGIN
  858.             Dfree(drive_buf, drive_id + 1 ) ;       (* it's a valid drive *)
  859.             temp := drive_buf[3] * drive_buf[4];    (* bytes per cluster *)
  860.             WriteV( byte_available, (drive_buf[1] * temp) : 8 ) ;
  861.             WriteV( byte_used, ((drive_buf[2] - drive_buf[1])* temp) : 8 ) ;
  862.             Set_DText( space_box, BYTEAVL, byte_available, System_Font,
  863.               TE_RIGHT ) ;
  864.             Set_DText( space_box, BYTEUSED, byte_used, System_Font, TE_RIGHT ) ;
  865.             Set_Mouse(M_Arrow) ;
  866.             Obj_SetState( space_box, btn, Normal, TRUE ) ;
  867.             Show_Dialog( space_box, ROOT ) ;
  868.           END
  869.         ELSE
  870.           BEGIN
  871.             Set_Mouse(M_ARROW) ;
  872.             End_Dialog( space_box ) ;
  873.             IO_Error( -15 ) ;
  874.             Obj_SetState( space_box, btn, Normal, FALSE ) ;
  875.             btn := DSCANBTN ;
  876.           END ;
  877.       END ;
  878.     EXIT IF btn=DSCANBTN ;
  879.     btn := Redo_Dialog( space_box, DISKID ) ;
  880.   END ;
  881.   Obj_SetState( space_box, btn, Normal, FALSE ) ;
  882.   dumy := Chdir( def_path ) ;
  883.   End_Dialog( space_box ) ;
  884. END ;
  885.  
  886.  
  887. PROCEDURE Rename_File ;
  888. (* renaming file *)
  889. VAR
  890.   old, new      : C_Path_Type ;
  891.   fhandle,
  892.   i             : Integer ;
  893.   tbuf          : time_buf ;
  894.   NewPath,
  895.   OldPath       : Path_Name ;
  896.   cont          : Boolean ;
  897. BEGIN
  898.   info_msg( 'Select file to be renamed FROM...' ) ;
  899.   OldPath := src_name ;
  900.   cont := Get_In_File( file_path1, OldPath ) ;
  901.   EraseInfo ;
  902.   IF cont AND (length(OldPath) <> 0) THEN
  903.     BEGIN
  904.       info_msg( 'Select file to be rename TO...' ) ;
  905.       temp_path := OldPath ;
  906.       Strip_Filename( temp_path, des_name ) ;
  907.       NewPath := des_name ;
  908.       cont := Get_In_File( file_path2, NewPath ) ;
  909.       EraseInfo ;
  910.       IF cont AND (length(NewPath) <> 0) THEN 
  911.         BEGIN            {Don't allow renamming to Self}
  912.           IF OldPath=NewPath THEN
  913.             BEGIN
  914.               IO_Error( -37 ) ;
  915.               cont := FALSE ;
  916.             END ;
  917.         END ;
  918.       IF cont THEN  
  919.         BEGIN
  920.           Strip_Filename( OldPath, src_name ) ;
  921.           Strip_Filename( NewPath, des_name ) ;
  922.           IF (src_name='') OR (des_name='') THEN
  923.             BEGIN        {Don't allow null file names}
  924.               IO_Error(-38) ;
  925.               cont := FALSE ;
  926.             END ;
  927.         END ;    
  928.       IF cont THEN cont := Chdir( OldPath ) ;
  929.       IF cont THEN  {Check if source file is read only - if so, error out}
  930.         BEGIN
  931.           SetDTA( Prog_DTA ) ;
  932.           P_To_CPath( src_name, old ) ;
  933.           i := SFirst( old, $01 ) ;
  934.           IF (i=0) AND cont THEN
  935.             BEGIN
  936.               IF Prog_DTA.attrib = $01 THEN
  937.                 BEGIN
  938.                   IO_Error( -36 ) ;
  939.                   cont := FALSE ;
  940.                 END ;
  941.             END
  942.           ELSE IF (i<>0) AND cont THEN {Error out if cannot find source}
  943.             BEGIN
  944.               IO_Error( i ) ;
  945.               cont := FALSE ;
  946.             END ;
  947.         END ;    
  948.       IF cont THEN cont := NOT FileConflict( OldPath, NewPath, FALSE ) ;
  949.       IF cont THEN
  950.         BEGIN
  951.           IF OldPath[1]<>NewPath[1] THEN {Simulate MOVE between drives}
  952.             BEGIN            {First copy the file}
  953.               cont := Copy_Files( src_name, des_name ) ;
  954.               IF cont THEN   {Get Source File's time/date stamp}
  955.                 BEGIN
  956.                   P_To_CPath( src_name, old ) ;
  957.                   fhandle := FOpen( old, 0 ) ;
  958.                   IF fhandle<0 THEN
  959.                     BEGIN
  960.                       IO_Error( fhandle ) ;
  961.                       cont := FALSE ;
  962.                     END
  963.                   ELSE
  964.                     BEGIN
  965.                       FDaTime( tbuf, fhandle, 0 ) ;
  966.                       FClose( fhandle ) ;
  967.                     END ;
  968.                 END ;    
  969.               IF cont THEN {Set copy's time/date stamp to source's}
  970.                 BEGIN
  971.                   P_To_CPath( des_name, new ) ;
  972.                   fhandle := FOpen( new, 2 ) ;
  973.                   IF fhandle<0 THEN
  974.                     BEGIN
  975.                       IO_Error( fhandle ) ;
  976.                       cont := FALSE ;
  977.                     END
  978.                   ELSE
  979.                     BEGIN
  980.                       FDaTime( tbuf, fhandle, 1 ) ;
  981.                       FClose( fhandle ) ;
  982.                     END ;
  983.                 END ;    
  984.               IF cont THEN {If move successful then Delete source}
  985.                 BEGIN
  986.                   P_To_CPath(src_name, old) ;
  987.                   IO_Error( FDelete(old) ) ;
  988.                 END ;
  989.             END  
  990.           ELSE    {Let GEMDOS do the MOVE/RENAME within a drive}
  991.             BEGIN   
  992.               P_To_CPath( des_name, new ) ;
  993.               i := FDelete( new ) ; {Delete preexisting new file}
  994.               IF (i=0) OR (i=-33) THEN  {for convenience}
  995.                 BEGIN
  996.                   P_To_CPath( src_name, old ) ;
  997.                   IO_Error( FRename( 0, old, new ) ) ;
  998.                 END
  999.               ELSE IO_Error( i ) ;
  1000.             END ;    
  1001.           cont := Chdir( def_path ) ;
  1002.         END ;
  1003.     END ;  
  1004. END ;
  1005.  
  1006.  
  1007. PROCEDURE Delete_File ;
  1008. {Delete file - No prompt but File selector - be sure you want to delete file!!!}
  1009. VAR
  1010.   fname : Path_name ;
  1011.   c_str : C_Path_Type ;
  1012.   continue : Boolean ;
  1013. BEGIN
  1014.   Info_Msg('Select File To Be Deleted...') ;
  1015.   continue := Get_In_File( file_path1, src_name ) ;
  1016.   EraseInfo ;
  1017.   IF continue AND (length(src_name) <> 0) THEN
  1018.     BEGIN
  1019.       Strip_Filename( src_name, fname ) ;
  1020.       continue := Chdir( src_name ) ;
  1021.       IF continue THEN
  1022.         BEGIN        {Check for tries to Delete Folders, and deny access}
  1023.           SetDTA( Prog_DTA ) ;
  1024.           P_To_CPath(fname, c_str) ;
  1025.           IF SFirst( c_str, $37 ) = 0 THEN
  1026.             BEGIN
  1027.               IF Prog_DTA.attrib = $10 THEN
  1028.                 BEGIN
  1029.                   continue := FALSE ;
  1030.                   IO_Error( -36 ) ;
  1031.                 END ;
  1032.             END ;
  1033.         END ;
  1034.       IF continue THEN IO_Error( FDelete(c_str) ) ;
  1035.       continue := Chdir( def_path ) ;
  1036.     END ;
  1037.   Menu_Normal( menu, MSPECIAL ) ;
  1038. END ;
  1039.  
  1040.  
  1041. PROCEDURE Set_Source ;
  1042. {Set working path to file to be edited and compiled}
  1043. VAR fname : Path_Name ;
  1044. BEGIN
  1045.   fname := '' ;
  1046.   info_msg( 'Set path to SOURCE files...' ) ;
  1047.   IF Get_In_File( file_path1, fname ) THEN work_path := file_path1 ;
  1048.   EraseInfo ;
  1049. END ;
  1050.       
  1051.  
  1052. PROCEDURE Locate_Programs ;
  1053. (* local filenames, similar to Pascal version 2. *)
  1054. VAR
  1055.   fpath,
  1056.   fname : Path_Name ;
  1057.   msg : Str255 ;
  1058.   l_box : Dialog_Ptr ;
  1059.   btn : Integer ;
  1060. BEGIN
  1061.   Find_Dialog( LOCATE, l_box ) ;
  1062.   Center_Dialog( l_box ) ;
  1063.   REPEAT
  1064.     btn := Do_Dialog( l_box, 0 ) ;
  1065.     CASE btn OF
  1066.       LEDIT   : BEGIN
  1067.                   msg := 'Select the EDITOR filename...' ;
  1068.                   fname := 'EDITOR.' ;
  1069.                 END ;
  1070.       LCMP    : BEGIN
  1071.                   msg := 'Select the COMPILER filename...' ;
  1072.                   fname := 'COMPILER.PRG' ;
  1073.                 END ;
  1074.       LLINK   : BEGIN
  1075.                   msg := 'Select the LINKER filename...' ;
  1076.                   fname := 'LINKER.PRG' ;
  1077.                 END ;
  1078.       LPASGEM : BEGIN
  1079.                   msg := 'Select the PASGEM filename...' ;
  1080.                   fname := 'PASGEM' ;
  1081.                 END ;
  1082.       LPASLIB : BEGIN
  1083.                   msg := 'Select the PASLIB filename...' ;
  1084.                   fname := 'PASLIB' ;
  1085.                 END ;
  1086.       LPRT    : BEGIN
  1087.                   msg := 'Select the PRINTER filename...' ;
  1088.                   fname := 'LISTPAS.PRG' ;
  1089.                 END ;
  1090.     END ;
  1091.     IF btn <> LOKBTN THEN BEGIN
  1092.       Info_Msg( msg ) ;
  1093.       IF Get_In_File( file_path1, fname ) AND (length(fname) <> 0) THEN
  1094.         BEGIN
  1095.           EraseInfo ;
  1096.           CASE btn OF
  1097.             LEDIT   : editor_name := fname ;
  1098.             LCMP    : compiler_name := fname ;
  1099.             LLINK   : linker_name := fname ;
  1100.             LPASGEM : pasgem_name := fname ;
  1101.             LPASLIB : paslib_name := fname ;
  1102.             LPRT    : printer_name := fname ;
  1103.           END ;
  1104.         END
  1105.       ELSE EraseInfo ;
  1106.     END ;
  1107.     Obj_SetState( l_box, btn, Normal, TRUE ) ;
  1108.   UNTIL btn = LOKBTN ;
  1109.   End_Dialog( l_box ) ;
  1110. END ;
  1111.  
  1112.  
  1113. PROCEDURE Read_Options( Fname : Path_name ; ShowError : Boolean ) ;
  1114. (* read options from the .INF file *)
  1115.   VAR
  1116.     f : text ;
  1117.     version : integer ;
  1118.     temp : integer ;
  1119.     opt : opt_range ;
  1120.   BEGIN
  1121.     IO_Check( false ) ;
  1122.     reset( f, Fname ) ;
  1123.     IO_Check( true ) ;
  1124.     temp := IO_Result ;
  1125.     IF temp = 0 THEN
  1126.       BEGIN
  1127.         readln( f, version ) ;
  1128.         FOR opt := 1 TO max_option DO
  1129.           IF opt IN [ ERRPAUSE,CHNLINK,DBGOPT,EDITCOMP,
  1130.                       STKOPT,RNGOPT,CLROPT,BAKOPT,NOCODE ]
  1131.            THEN
  1132.             BEGIN
  1133.               readln( f, temp ) ;
  1134.               cmp_opts[ opt ] := temp <> 0 ;
  1135.             END ;
  1136.         readln( f, for_gem ) ; (* 1 for GEM, 2 for TOS, 3 for TTP, 4 for ACC *)
  1137.         readln( f, addl_files ) ;
  1138.         readln( f, addl_libs ) ;
  1139.         readln( f, backup_path ) ;
  1140.         readln( f, editor_name ) ;
  1141.         readln( f, compiler_name ) ;
  1142.         readln( f, linker_name ) ;
  1143.         readln( f, pasgem_name ) ;
  1144.         readln( f, paslib_name ) ;
  1145.         readln( f, printer_name ) ;
  1146.         readln( f, work_path ) ;
  1147.         close( f ) ;
  1148.         file_path1 := work_path ;
  1149.         Strip_Filename( file_path1, temp_path ) ;
  1150.         file_path1 := concat( file_path1, '*.*' ) ;       (* used by SPECIALS *)
  1151.         file_path2 := file_path1 ;
  1152.       END
  1153.     ELSE IF ShowError THEN IO_Error( temp ) ;
  1154.   END ;
  1155.  
  1156.  
  1157. PROCEDURE Load_Options ;
  1158. {Load new option file from path given}
  1159. VAR
  1160.     NewPath,
  1161.     NewFile : Path_Name ;
  1162.     continue : Boolean ;
  1163.   BEGIN
  1164.     Info_Msg('Select Option Filename To Be LOADED...') ;
  1165.     NewFile := 'PASCALM.INF' ;
  1166.     NewPath := Concat( def_path, '*.INF' ) ;
  1167.     continue := Get_In_File( NewPath, NewFile ) ;
  1168.     EraseInfo ;
  1169.     IF continue AND (length(NewFile) <> 0) THEN
  1170.       BEGIN
  1171.         NewPath := NewFile ;
  1172.         Strip_Filename( NewPath, NewFile ) ;
  1173.         continue := Chdir( NewPath ) ;
  1174.         IF continue THEN
  1175.           BEGIN
  1176.             Read_Options( NewFile, TRUE ) ;
  1177.             continue := Chdir( def_path ) ;
  1178.           END ;  
  1179.       END ;
  1180.   END ;
  1181.         
  1182.  
  1183. PROCEDURE Save_Options ;
  1184. (* sace options to the .INF file *)
  1185.   VAR
  1186.     NewPath,
  1187.     NewFile : Path_Name ;
  1188.     f : text ;
  1189.     opt : opt_range ;
  1190.     continue : Boolean ;
  1191.   BEGIN
  1192.     Info_Msg('Select Option Filename To Be SAVED...') ;
  1193.     NewFile := 'PASCALM.INF' ;
  1194.     NewPath := Concat( def_path, '*.INF' ) ;
  1195.     continue := Get_In_File( NewPath, NewFile ) ;
  1196.     EraseInfo ;
  1197.     IF continue AND (length(NewFile) <> 0) THEN
  1198.       BEGIN
  1199.         NewPath := NewFile ;
  1200.         Strip_Filename( NewPath, NewFile ) ;
  1201.         continue := Chdir( NewPath ) ;
  1202.         IF continue THEN
  1203.           BEGIN
  1204.             IO_Check( false ) ;
  1205.             rewrite( f, NewFile ) ;
  1206.             IO_Check( true ) ;
  1207.             IF (IO_Result <> 0) THEN IO_Error( IO_Result )
  1208.             ELSE
  1209.               BEGIN
  1210.                 Set_Mouse( M_BEE ) ;         (* busy saving file *)
  1211.                 writeln( f, $100:1 ) ;  (* Version 1.00 *)
  1212.                 FOR opt := 1 TO max_option DO
  1213.                   IF opt IN [ ERRPAUSE,CHNLINK,DBGOPT,EDITCOMP,STKOPT,
  1214.                       RNGOPT,CLROPT,BAKOPT,NOCODE ]
  1215.                       THEN writeln( f, ord( cmp_opts[opt] ):1 ) ;
  1216.                 writeln( f, for_gem ) ;
  1217.                 writeln( f, addl_files ) ;
  1218.                 writeln( f, addl_libs ) ;
  1219.                 writeln( f, backup_path ) ;
  1220.                 writeln( f, editor_name ) ;
  1221.                 writeln( f, compiler_name ) ;
  1222.                 writeln( f, linker_name ) ;
  1223.                 writeln( f, pasgem_name ) ;
  1224.                 writeln( f, paslib_name ) ;
  1225.                 writeln( f, printer_name ) ;
  1226.                 writeln( f, work_path ) ;
  1227.                 close( f ) ;
  1228.                 Set_Mouse( M_ARROW ) ;
  1229.               END ;
  1230.             continue := Chdir( def_path ) ;  
  1231.           END
  1232.       END        
  1233.   END ;
  1234.  
  1235.  
  1236. PROCEDURE out_esc( c : char ) ;
  1237. {For TOS screen control VT-52}
  1238.   BEGIN
  1239.     bconout( 2, 27 ) ;
  1240.     bconout( 2, ord(c) ) ;
  1241.   END ;
  1242.  
  1243.  
  1244. PROCEDURE Tos_Screen ;
  1245.   BEGIN
  1246.     Hide_Mouse ;
  1247.     out_esc( 'E' ) ;        (* Clear screen *)
  1248.     out_esc( 'e' ) ;        (* and cursor on *)
  1249.   END ;
  1250.  
  1251.  
  1252. PROCEDURE Gem_Screen ;
  1253.   BEGIN
  1254.     out_esc( 'f' ) ;        (* Cursor off *)
  1255.     Show_Mouse ;
  1256.   END ;
  1257.  
  1258.  
  1259. FUNCTION VerifyPath( prog : Path_Name ) : Boolean ;
  1260. {Verify program path name before attempt to run it}
  1261. VAR filename : Path_Name ;
  1262.     C_name : C_Path_Type ;
  1263.     cont : Boolean ;
  1264.     error : Integer ;
  1265. BEGIN
  1266.   Strip_Filename( prog, filename ) ;
  1267.   cont := Chdir( prog ) ;
  1268.   IF cont THEN
  1269.     BEGIN
  1270.       P_To_CPath( filename, C_name ) ;
  1271.       error := SFirst( C_name, $01 ) ;
  1272.       IF error<>0 THEN
  1273.         BEGIN
  1274.           Redraw_Screen ;
  1275.           IO_Error( error ) ;
  1276.           cont := FALSE ;
  1277.         END ;
  1278.     END ;
  1279.   VerifyPath := cont ;
  1280.   cont := Chdir( def_path ) ;
  1281. END ;            
  1282.  
  1283.  
  1284. FUNCTION Call_Overlay( prog : Path_Name ; VAR cmd_line : Str255 ;
  1285.                             tos : boolean ) : integer ;
  1286. (* call editor, compiler, linker *)
  1287.   VAR
  1288.     i : integer ;
  1289.     prog_name : C_Path_Type ;
  1290.     tail : C_String ;
  1291.  
  1292.   FUNCTION p_exec( load : integer ; VAR name : C_Path_Type;
  1293.                    VAR tail : C_String ; VAR envp : env_ptr ) : integer ;
  1294.     GEMDOS( $4B ) ;
  1295.  
  1296.   BEGIN
  1297.     FOR i := 1 TO length( cmd_line ) DO
  1298.       tail[i] := cmd_line[i] ;
  1299.     tail[ length(cmd_line)+1 ] := chr(0) ;
  1300.     tail[0] := chr( length(cmd_line) ) ;
  1301.     P_To_CPath( prog, prog_name ) ;
  1302.     Erase_Menu( menu ) ;
  1303.     IF tos THEN Tos_Screen ;
  1304.     Call_Overlay := p_exec( 0, prog_name, tail, envp ) ;
  1305.     IF tos THEN Gem_Screen ;
  1306.     Redraw_Screen ;
  1307.     Draw_Menu( menu ) ;
  1308.   END ;
  1309.  
  1310.  
  1311. PROCEDURE Print_File ;
  1312. {Calls a generic PRINT file; no PARAMETERS are passed}
  1313. {default path switched to work path for the PRINT files usage}
  1314. VAR
  1315.     junk : integer ;
  1316.     prog_name : C_Path_Type ;
  1317.     tail : C_String ;
  1318.     gem : Boolean ;
  1319.     NewPath : Path_Name ;
  1320.  
  1321.   FUNCTION p_exec( load : integer ; VAR name : C_Path_Type;
  1322.                    VAR tail : C_String ; VAR envp : env_ptr ) : integer ;
  1323.     GEMDOS( $4B ) ;
  1324.  
  1325. BEGIN
  1326.   IF VerifyPath( printer_name ) THEN
  1327.     BEGIN
  1328.       tail[0] := Chr(0) ;
  1329.       tail[1] := chr(0) ;
  1330.       NewPath := work_path ;
  1331.       Strip_Filename( NewPath, temp_path ) ;
  1332.       gem := Chdir( NewPath ) ;
  1333.       P_To_CPath( printer_name, prog_name ) ;
  1334.       gem := Is_GEM_Name( printer_name ) ;
  1335.       IF NOT gem THEN Tos_Screen ;
  1336.       junk := p_exec( 0, prog_name, tail, envp ) ;
  1337.       IF NOT gem THEN Gem_Screen ;
  1338.       gem := Chdir( def_path ) ;
  1339.       Redraw_Screen ;
  1340.     END ;  
  1341. END ;
  1342.  
  1343.  
  1344. PROCEDURE Create_Folder ;
  1345. {Make a new directory}
  1346. VAR
  1347.     Folder,
  1348.     NewPath : Path_Name ;
  1349.     continue : Boolean ;
  1350.     Cname : C_Path_Type ;
  1351.  
  1352.   BEGIN
  1353.     Info_Msg('Select Folder Name To Be CREATED...') ;
  1354.     NewPath := '' ;
  1355.     continue := Get_In_File( file_path1, NewPath ) ;
  1356.     EraseInfo ;
  1357.     IF continue AND (length(NewPath) <> 0) THEN
  1358.       BEGIN
  1359.         Strip_Filename( NewPath, Folder ) ;
  1360.         IF Folder='' THEN
  1361.           BEGIN
  1362.             IO_Error(-34) ;
  1363.             continue := FALSE ;
  1364.           END
  1365.         ELSE continue := Chdir( NewPath ) ;
  1366.         IF continue THEN 
  1367.           BEGIN
  1368.             P_To_CPath( Folder, Cname ) ;
  1369.             IF SFirst(Cname, $37)=0 THEN IO_Error( -36 ) 
  1370.             ELSE IO_Error( Mkdir( Cname ) ) ;
  1371.             continue := Chdir( def_path ) ;
  1372.           END ;
  1373.       END ;      
  1374.   END ;
  1375.  
  1376.  
  1377. FUNCTION Delete_Folder( VAR RPath, FPath, FldName : Path_Name ) : Boolean ;
  1378. {Delete Folder - this routine clears out all files and folders within}
  1379. {the folder to be deleted by calling itself}
  1380. VAR
  1381.     MoreFiles,
  1382.     return      : Integer ;
  1383.     dumy,
  1384.     continue    : Boolean ;
  1385.     ReturnPath,
  1386.     FolderPath,
  1387.     FolderName,
  1388.     Fname,
  1389.     FolderContents : Path_Name ;
  1390.     C_Temp,
  1391.     Cname       : C_Path_Type ;
  1392. BEGIN
  1393.   ReturnPath := RPath ;  {The paths to the folders are passed with pointers} 
  1394.   FolderPath := FPath ;  {to save stack space. Those pointers can not be used}
  1395.   FolderName := FldName ; {in a recursive procedure, and have to be copied}
  1396.   FolderContents := Concat( FolderPath, FolderName, '\' ) ;
  1397.   continue := Chdir( FolderContents ) ;
  1398.   Fname := '*.*' ;
  1399.   P_To_CPath( Fname, Cname ) ;
  1400.   MoreFiles := SFirst(Cname,$37) ; {Get name and attribute of each file entry}
  1401.   WITH Prog_DTA DO                 {and delete it!}
  1402.     BEGIN
  1403.       WHILE (MoreFiles=0) AND continue DO
  1404.         BEGIN
  1405.           IF attrib=$10 THEN {Directory files}
  1406.             BEGIN
  1407.               IF name[1]<>'.' THEN {Ignore "." directory entries pointing to}
  1408.                 BEGIN              {parent and subdirectories}
  1409.                   C_To_PPath( name, Fname ) ;
  1410.                   continue := Delete_Folder( FolderContents, FolderContents, Fname ) ;
  1411.                   MoreFiles := SFirst(Cname,$37) ;
  1412.                 END
  1413.               ELSE MoreFiles := SNext ;    
  1414.             END
  1415.           ELSE IF attrib=$01 THEN {Unprotect write protected files first}
  1416.             BEGIN                 {then delete them}
  1417.              return := Chmod( name, 1, 0 ) ;
  1418.              IF return>0 THEN return := -5 ;
  1419.              IF return<0 THEN
  1420.                BEGIN
  1421.                 IO_Error( return ) ;
  1422.                 continue := FALSE ;
  1423.                END
  1424.              ELSE 
  1425.                BEGIN
  1426.                  return := FDelete( name ) ;
  1427.                  IF return<>0 THEN
  1428.                    BEGIN
  1429.                      IO_Error( return ) ;
  1430.                      continue := FALSE ;
  1431.                    END ;
  1432.                END ;
  1433.              MoreFiles := SNext ;  
  1434.             END
  1435.           ELSE                  {Else delete all other files}
  1436.             BEGIN         
  1437.               return := FDelete( name ) ;
  1438.               IF return<>0 THEN
  1439.                 BEGIN
  1440.                   IO_Error( return ) ;
  1441.                   continue := FALSE ;
  1442.                 END ;
  1443.               MoreFiles := SNext ;  
  1444.             END ;
  1445.         END ;    
  1446.     END ;
  1447.   IF continue THEN {If the folder has been cleared out, delete it then!}
  1448.     BEGIN
  1449.       continue := Chdir( FolderPath ) ;
  1450.       IF continue THEN
  1451.         BEGIN
  1452.           P_To_CPath( FolderName, Cname ) ;
  1453.           return := DDelete( Cname ) ;
  1454.           IF return<>0 THEN
  1455.             BEGIN
  1456.               IO_Error( return ) ;
  1457.               continue := FALSE ;
  1458.             END ;
  1459.         END ;
  1460.     END ;
  1461.   dumy := Chdir( ReturnPath ) ; {Return to starting pathway}
  1462.   Delete_Folder := continue ;
  1463. END ;
  1464.  
  1465.  
  1466. PROCEDURE Setup_DFolder ;
  1467. {Routine to ask which folder to delete - NOTE: only the PATH, not the}
  1468. {returned filename from the File Selector is examined}
  1469. VAR
  1470.     len,
  1471.     choice : Integer ;
  1472.     AlertStr : Str255 ;
  1473.     F_path,
  1474.     Folder : Path_Name ;
  1475.     continue : Boolean ;
  1476. BEGIN
  1477.   info_msg( 'Set Path To The FOLDER To Be DELETED...' ) ;
  1478.   F_path := '' ;
  1479.   continue := Get_In_File( file_path1, F_path ) ;
  1480.   EraseInfo ;
  1481.   IF continue THEN
  1482.     BEGIN
  1483.       F_path := file_path1 ;
  1484.       IF F_path[2]<>':' THEN
  1485.         BEGIN
  1486.           continue := FALSE ;
  1487.           IO_Error(-34) ;
  1488.         END
  1489.       ELSE
  1490.         BEGIN    
  1491.           Strip_Filename( F_path, Folder ) ;
  1492.           len := Length( F_path ) ;
  1493.           IF (len<5) OR (F_path[len]<>'\') THEN
  1494.             BEGIN
  1495.               continue := FALSE ;
  1496.               IO_Error( -34 ) ;
  1497.             END 
  1498.           ELSE continue := Chdir( F_path ) ;
  1499.         END ;
  1500.     END ;    
  1501.   IF continue THEN  {If user wants to delete folder, give him a chance to}
  1502.     BEGIN           {back out, and list folder name for him!!!}
  1503.       F_path[0] := Chr(len-1) ;
  1504.       Strip_Filename( F_path, Folder ) ;
  1505.       file_path1 := F_path ;
  1506.       AlertStr := '[2][|Are you sure that you wish to|delete the entire ' ;
  1507.       AlertStr := Concat( AlertStr, 'contents of|folder "', FOLDER, '"...][ YES | NO ]' ) ;
  1508.       choice := Do_Alert( AlertStr, 1 ) ;
  1509.       IF choice <> 1 THEN continue := FALSE ;
  1510.     END ;
  1511.   IF continue THEN
  1512.     BEGIN
  1513.       Set_Mouse( M_Bee ) ;
  1514.       SetDTA( Prog_DTA ) ;
  1515.       continue := Delete_Folder( def_path, F_path, Folder ) ;
  1516.       Set_Mouse( M_Arrow ) ;
  1517.     END ;
  1518.   continue := Chdir( def_path ) ;  
  1519.   Menu_Normal( menu, MSPECIAL ) ;
  1520. END ;
  1521.  
  1522.           
  1523. PROCEDURE Strip_Extension( VAR fn : Path_Name ) ;
  1524. (* Strip_Extension - Remove the extension from a Path_Name variable. *)
  1525.   VAR
  1526.     i : integer ;
  1527.     done : boolean ;
  1528.   BEGIN
  1529.     i := length( fn ) ;
  1530.     done := false ;
  1531.     WHILE NOT done DO
  1532.       BEGIN
  1533.         IF i < 1 THEN
  1534.           done := true
  1535.         ELSE IF (fn[i] = ':') OR (fn[i] = '\') THEN
  1536.           done := true
  1537.         ELSE IF fn[i] = '.' THEN
  1538.           BEGIN
  1539.             fn[0] := chr(i-1) ;
  1540.             done := true ;
  1541.           END
  1542.         ELSE
  1543.           i := i - 1 ;
  1544.       END ;
  1545.   END ;
  1546.  
  1547.  
  1548. PROCEDURE Do_Link( name : Path_Name ; for_gem : integer ) ;
  1549. (* Do_Link - Call the linker with a desired file as input. *)
  1550.   VAR
  1551.     run_save : Path_Name ;
  1552.     ReturnCode : integer ;
  1553.     extension : STRING [ 5 ] ;
  1554.     libs,
  1555.     cmd_line : Str255 ;
  1556.     x, y, w, h : integer ;
  1557.     dial : Dialog_Ptr ;
  1558.   BEGIN
  1559.     IF VerifyPath( linker_name ) THEN
  1560.       BEGIN
  1561.         Strip_Extension( name ) ;
  1562.         cmd_line := name ;
  1563.         run_save := name ;
  1564.         link_name := concat( name , '.O' ) ;
  1565.         CASE for_gem OF
  1566.           GEM_O : extension := '.PRG=' ;
  1567.           ACC_O : extension := '.ACC=' ;
  1568.           TOS_O : extension := '.TOS=' ;
  1569.           TTP_O : extension := '.TTP=' ;
  1570.         END ;
  1571.         CASE for_gem OF
  1572.           GEM_O, ACC_O : libs := concat(',', pasgem_name, ',', paslib_name) ;
  1573.           TOS_O, TTP_O : libs := concat(',', paslib_name) ;
  1574.         END ;
  1575.         cmd_line := concat( '! ', name, extension, name ) ;
  1576.         IF length(addl_files) > 0 THEN
  1577.           cmd_line := concat( cmd_line, ',', addl_files ) ;
  1578.         IF length(addl_libs) > 0 THEN
  1579.           cmd_line := concat( cmd_line, ',', addl_libs ) ;
  1580.         cmd_line := concat( cmd_line, libs ) ;
  1581.         Find_Dialog( LOADING, dial ) ;
  1582.         Set_DText( dial, LOADNAME, 'Loading overlay LINKER.PRG', System_Font, TE_Left ) ;
  1583.         Center_Dialog( dial ) ;
  1584.         Show_Dialog( dial, Root ) ;
  1585.         ReturnCode := Call_Overlay( linker_name, cmd_line, false ) ;
  1586.         IF ReturnCode = 0 THEN 
  1587.           BEGIN
  1588.             CASE for_gem OF
  1589.               GEM_O : run_name := concat( run_save, '.PRG' ) ;
  1590.               ACC_O : run_name := '' ;
  1591.               TOS_O : run_name := concat( run_save, '.TOS' ) ;
  1592.               TTP_O : run_name := concat( run_save, '.TTP' ) ;
  1593.               END ;
  1594.           END ;
  1595.       END ;    
  1596.   END ;
  1597.  
  1598.  
  1599. FUNCTION Do_Compile : integer ;
  1600. (* Do_Compile - Call the compiler with a desired file as input. *)
  1601.   VAR
  1602.     cmp_code : integer ;
  1603.     cmd_line : Str255 ;
  1604.     src,
  1605.     des,
  1606.     name : Path_Name ;
  1607.     x, y, w, h,
  1608.     i : integer ;
  1609.     dial : Dialog_Ptr ;
  1610.     dumy : Boolean ;
  1611.   BEGIN
  1612.     IF VerifyPath( compiler_name ) THEN
  1613.       BEGIN
  1614.         name := compile_name ;  {Note usage of separate file compile name from}
  1615.         Strip_Extension( name ) ; {file edit name}
  1616.         cmd_line := concat( name, '  /UGEM' ) ;
  1617.         CASE for_gem OF
  1618.           GEM_O : cmd_line := concat( cmd_line, ' /GEM' ) ;
  1619.           ACC_O : cmd_line := concat( cmd_line, ' /ACC' ) ;
  1620.         END ;
  1621.         IF cmp_opts[ ERRPAUSE ] THEN
  1622.           cmd_line := concat( cmd_line, ' /PAUSE' ) ;
  1623.         IF cmp_opts[ DBGOPT ] THEN
  1624.           cmd_line := concat( cmd_line, ' /DEBUG' ) ;
  1625.         IF NOT cmp_opts[ STKOPT ] THEN
  1626.           cmd_line := concat( cmd_line, ' /NOCHECK' ) ;
  1627.         IF cmp_opts[ RNGOPT ] THEN
  1628.           cmd_line := concat( cmd_line, ' /CHECK' ) ;
  1629.         IF cmp_opts[ CLROPT ] THEN
  1630.           cmd_line := concat( cmd_line, ' /CLEAR' ) ;
  1631.         IF cmp_opts[ NOCODE ] THEN
  1632.           cmd_line := concat( cmd_line, ' /NOCODE' ) ;
  1633.         Find_Dialog( LOADING, dial ) ;
  1634.         Set_DText( dial, LOADNAME, 'Loading overlay COMPILER.PRG', System_Font, TE_Left ) ;
  1635.         Center_Dialog( dial ) ;
  1636.         Show_Dialog( dial, Root ) ;
  1637.         cmp_code := Call_Overlay( compiler_name, cmd_line, false ) ;
  1638.         Do_Compile := 0 ;
  1639.         IF cmp_code = 2 THEN        (* User wants to edit! *)
  1640.          BEGIN
  1641.             Do_Compile := 1 ;
  1642.             i := 0 ;
  1643.             WHILE envp^[i] <> chr(0) DO
  1644.               BEGIN
  1645.                 edit_name[i+1] := envp^[i] ;
  1646.                 i := i + 1 ;
  1647.               END ;
  1648.             edit_name[0] := chr(i) ;
  1649.           END
  1650.         ELSE BEGIN
  1651.           IF (cmp_code = 0) AND (cmp_opts[ BAKOPT ]) THEN
  1652.             BEGIN {Copy back EDIT file only, unless not defined yet}
  1653.               Find_Dialog( LOADING, dial ) ;
  1654.               Set_DText( dial, LOADNAME, 'Automatic BACKUP in progress',
  1655.                 System_Font, TE_Left ) ;    {Show our intentions to}
  1656.               Center_Dialog( dial ) ;       {do AUTO backup}
  1657.               Show_Dialog( dial, Root ) ;
  1658.               IF Length(edit_name)=0 THEN src := compile_name
  1659.               ELSE src := edit_name ;
  1660.               Strip_Filename( src, des ) ;
  1661.               src := Concat( src, des ) ;
  1662.               des := Concat( backup_path, des ) ;
  1663.               dumy := Copy_Files( src, des ) ;
  1664.             END ;
  1665.           IF (cmp_code = 0) AND (cmp_opts[ CHNLINK ]) THEN
  1666.             Do_Link( name, for_gem )
  1667.           ELSE End_Dialog( dial ) ;
  1668.         END ;
  1669.       END
  1670.     ELSE Do_Compile := 0 ;      
  1671.   END ;
  1672.  
  1673.  
  1674. FUNCTION Do_Edit : integer ;
  1675.   VAR
  1676.     cmd_line : Str255 ;
  1677.     i : integer ;
  1678.     is_tos : boolean ;
  1679.     path : C_Path_Type ;
  1680.     fn,
  1681.     WorkPath : Path_Name ;
  1682.     dumy : Boolean ;
  1683.  
  1684.   BEGIN
  1685.     IF VerifyPath( editor_name ) THEN
  1686.       BEGIN
  1687.         cmd_line := edit_name ;
  1688.         is_tos := Is_TTP_Name( editor_name ) ;  (* allow using different type of
  1689.                                                  editors *)
  1690.         WorkPath := editor_name ;                                               
  1691.         Strip_Filename( WorkPath, fn ) ;
  1692.         IF Chdir( WorkPath ) THEN  {Reset path to editor pathname for editor to}
  1693.           BEGIN                    {finds its resource file}
  1694.             Wind_Update( End_Mctrl ) ;                                             
  1695.             IF Call_Overlay( editor_name, cmd_line, is_tos ) = 1 THEN
  1696.               Do_Edit := 2
  1697.             ELSE Do_Edit := 0 ;
  1698.             Wind_Update( Beg_Mctrl ) ;
  1699.             dumy := Chdir( def_path ) ;
  1700.           END
  1701.         ELSE Do_Edit := 0 ;
  1702.       END
  1703.     ELSE Do_Edit := 0 ;     
  1704.   END ;
  1705.  
  1706.  
  1707. PROCEDURE Compile_Edit( which : integer ; GetFile : boolean ) ;
  1708. (* Compile_Edit - Loop for "compile-edit-link" process. *)
  1709. (* which : 1   Editor
  1710.            2   Compiler
  1711. *)
  1712.   VAR
  1713.     FileLen,
  1714.     i : integer ;
  1715.     cont : boolean ;
  1716.   BEGIN
  1717.     Strip_Extension( work_path ) ;
  1718.     work_path := concat( work_path, '.PAS' ) ;
  1719.     cont := TRUE ;
  1720.     IF which=1 THEN FileLen := Length(edit_name)
  1721.     ELSE FileLen := Length(compile_name ) ;
  1722.     IF GetFile OR (FileLen=0) THEN
  1723.       BEGIN
  1724.         IF which=1 THEN
  1725.           BEGIN
  1726.             info_msg('Select File To Be Edited...') ;
  1727.             cont := Get_In_File( work_path, edit_name ) ;
  1728.             FileLen := Length( edit_name ) ;
  1729.             GetFile := FALSE ;
  1730.           END  
  1731.         ELSE IF which=2 THEN
  1732.           BEGIN
  1733.             info_msg('Select File To Be Compiled...') ;
  1734.             cont := Get_In_File( work_path, compile_name ) ;
  1735.             FileLen := Length( compile_name ) ;
  1736.           END ;  
  1737.         EraseInfo ;
  1738.       END ;  
  1739.     IF cont  AND (FileLen <> 0) THEN BEGIN
  1740.       WHILE which <> 0 DO
  1741.         BEGIN
  1742.           IF which = 1 THEN     (* Editor phase! *)
  1743.             BEGIN
  1744.               which := Do_Edit ;
  1745.             END (* IF *)
  1746.           ELSE
  1747.             BEGIN
  1748.               IF (Length(compile_name)=0) OR
  1749.                 (cmp_opts[EDITCOMP] AND (Length(edit_name)>0)
  1750.                 AND (NOT GETFILE)) THEN
  1751.                 BEGIN
  1752.                   compile_name := edit_name ;
  1753.                   FOR i := length( compile_name ) DOWNTO 1 DO
  1754.                     IF compile_name[i] = ' ' THEN
  1755.                       compile_name[0] := chr( i-1 ) ;
  1756.                 END ;      
  1757.               which := Do_Compile ;
  1758.               GETFILE := FALSE ;
  1759.             END ;  
  1760.         END ; (* WHILE *)
  1761.     END  (* IF *)
  1762.   END ;
  1763.  
  1764.  
  1765. PROCEDURE Call_Linker( GetFile : Boolean ) ;
  1766. {CAll linker program}
  1767. VAR cont : Boolean ;
  1768.   BEGIN
  1769.     Strip_Extension( work_path ) ;
  1770.     work_path := concat( work_path, '.O' ) ;
  1771.     cont := TRUE ;
  1772.     IF GetFile OR (length(link_name)=0) THEN
  1773.       BEGIN
  1774.         info_msg('Select File To Be Linked...') ;
  1775.         cont := Get_In_File( work_path, link_name ) ;
  1776.         EraseInfo ;
  1777.       END ;  
  1778.     IF cont AND (length(link_name) <> 0)
  1779.     THEN BEGIN
  1780.       Do_Link( link_name, for_gem ) ;
  1781.     END  (* IF *)
  1782.     ELSE
  1783.   END ;
  1784.  
  1785. {$P-}
  1786.  
  1787. PROCEDURE Call_Program( GetFile : boolean ) ;
  1788. {Run another program}
  1789.   TYPE
  1790.     environment = PACKED ARRAY [ 1..9 ] OF char ;
  1791.   VAR
  1792.     cont,
  1793.     skip : boolean ;
  1794.     i : integer ;
  1795.     name : C_Path_Type ;
  1796.     tail : C_String ;
  1797.     cmd_line : Str255 ;
  1798.     env : environment ;
  1799.     run_gem : boolean ;
  1800.     ttp_box : Dialog_Ptr ;
  1801.     tmp_work_path,
  1802.     run_path : Path_Name ;
  1803.  
  1804.   PROCEDURE p_exec( load : integer ; VAR name : C_Path_Type ;
  1805.                     VAR tail : C_String ; VAR env : environment ) ;
  1806.     GEMDOS( $4B ) ;
  1807.  
  1808.   BEGIN
  1809.     tmp_work_path := work_path ;
  1810.     skip := FALSE ;
  1811.     Strip_Extension( tmp_work_path ) ;
  1812.     CASE for_gem OF
  1813.       GEM_O :  tmp_work_path := concat( tmp_work_path, '.PRG' ) ;
  1814.       TOS_O :  tmp_work_path := concat( tmp_work_path, '.TOS' ) ;
  1815.       TTP_O :  tmp_work_path := concat( tmp_work_path, '.TTP' ) ;
  1816.     END ;
  1817.     cont := TRUE ;
  1818.     IF GetFile OR (length(run_name)=0) THEN
  1819.       BEGIN
  1820.         info_msg('Select File To Be Run...') ;
  1821.         cont := Get_In_File( tmp_work_path, run_name ) ;
  1822.         EraseInfo ;
  1823.       END ;
  1824.     Wind_Update( End_Mctrl ) ;    
  1825.     IF cont AND (length(run_name) <> 0) THEN
  1826.       BEGIN
  1827.         run_path := run_name ;
  1828.         IF VerifyPath( run_name ) THEN
  1829.           BEGIN
  1830.             Strip_Filename( run_path, tmp_work_path ) ;
  1831.             IF Chdir( run_path ) THEN {reset current path for file to be run}
  1832.               BEGIN
  1833.                 P_To_CPath( run_name, name ) ;
  1834.                 env := 'PATH=A:\ ' ;
  1835.                 env[9] := chr(0) ;
  1836.                 run_gem := Is_Gem_Name( run_name ) ;
  1837.                 IF Is_TTP_Name( run_name ) THEN
  1838.                   BEGIN
  1839.                     IF Get_CMD( run_name, cmd_line ) THEN
  1840.                       BEGIN ; (* get command line *)
  1841.                         FOR i := 1 TO length( cmd_line ) DO
  1842.                           tail[i] := cmd_line[i] ;
  1843.                         tail[ length(cmd_line)+1 ] := chr(0) ;
  1844.                         tail[0] := chr( length(cmd_line) ) ;
  1845.                       END
  1846.                     ELSE
  1847.                       skip := TRUE ;
  1848.                   END
  1849.                 ELSE
  1850.                   BEGIN
  1851.                     tail[0] := chr(0) ;
  1852.                     tail[1] := chr(0) ;
  1853.                   END ;
  1854.                 IF NOT skip THEN BEGIN
  1855.                   Erase_Menu( menu ) ;
  1856.                   IF NOT run_gem THEN Tos_Screen ;
  1857.                   p_exec( 0, name, tail, env ) ;
  1858.                   IF NOT run_gem THEN
  1859.                     BEGIN
  1860.                       writeln( 'Hit any key to continue...' ) ;
  1861.                       bconin( 2 ) ;       (* Get a key from the BIOS! *)
  1862.                       Gem_Screen ;
  1863.                     END ;
  1864.                   cont := Chdir( def_path ) ; {Reset path back to default}
  1865.                   Redraw_Screen ;
  1866.                   i := Front_Window ; {Get rid of windows left on our screen by}
  1867.                   WHILE i>0 DO        {poorly designed programs - eg: ST Basic!}
  1868.                     BEGIN
  1869.                       Close_Window( i ) ;
  1870.                       Delete_Window( i ) ;
  1871.                       i := Front_Window ;
  1872.                     END ;  
  1873.                   Draw_Menu( menu ) ;
  1874.                   Intin^[0] := 0 ; {More reliable routine to make sure Mouse}
  1875.                   Linea_Showms ;   {shows after running programs}
  1876.                   Set_Mouse( M_Arrow ) ;
  1877.               END ;
  1878.           END ;    
  1879.         END ; (* not skip *)
  1880.       END ; (* get filename *)
  1881.   END ;
  1882.  
  1883. {$P=}
  1884.  
  1885. PROCEDURE Link_Options ;
  1886. {Read in link options}
  1887.   VAR
  1888.     dial : Dialog_Ptr ;
  1889.     opt,
  1890.     button : integer ;
  1891.   BEGIN
  1892.     Find_Dialog( LNKOPTS, dial ) ;
  1893.     Center_Dialog( dial ) ;
  1894.     FOR opt := 1 TO max_option DO
  1895.       IF opt IN [ LFORGEM,LFORTOS,LFORTTP,LFORACC ] THEN
  1896.         Obj_SetState( dial, opt, Normal, false ) ; (* reset every buttons *)
  1897.     CASE for_gem OF
  1898.       GEM_O :  Obj_SetState( dial, LFORGEM, Selected, false ) ;
  1899.       TOS_O :  Obj_SetState( dial, LFORTOS, Selected, false ) ;
  1900.       TTP_O :  Obj_SetState( dial, LFORTTP, Selected, false ) ;
  1901.       ACC_O :  Obj_SetState( dial, LFORACC, Selected, false ) ;
  1902.     END ;
  1903.     Set_DText( dial, LNKADDL, addl_files, System_Font, TE_Left ) ;
  1904.     Set_DText( dial, LNKLIBS, addl_libs, System_Font, TE_Left ) ;
  1905.     button := Do_Dialog( dial, LNKADDL ) ;
  1906.     End_Dialog( dial ) ;
  1907.     Obj_SetState( dial, button, Normal, FALSE ) ;
  1908.     IF button = LNKOK THEN
  1909.       BEGIN
  1910.         IF Obj_State( dial, LFORGEM ) = Selected THEN
  1911.           for_gem := GEM_O ;
  1912.         IF Obj_State( dial, LFORTOS ) = Selected THEN
  1913.           for_gem := TOS_O ;
  1914.         IF Obj_State( dial, LFORTTP ) = Selected THEN
  1915.           for_gem := TTP_O ;
  1916.         IF Obj_State( dial, LFORACC ) = Selected THEN
  1917.           for_gem := ACC_O ;
  1918.         Get_DEdit( dial, LNKADDL, addl_files ) ;
  1919.         Get_DEdit( dial, LNKLIBS, addl_libs ) ;
  1920.       END ;
  1921.   END ;
  1922.  
  1923.  
  1924. (* Compiler_Options - Allow the user to change various options within the
  1925.     compiler by activating the "Personal Pascal Compiler Options" dialog. *)
  1926.  
  1927. PROCEDURE Compiler_Options ;
  1928.   VAR
  1929.     dial : Dialog_Ptr ;
  1930.     button : integer ;
  1931.     opt : opt_range ;
  1932.   BEGIN
  1933.     Find_Dialog( CMPOPTS, dial ) ;
  1934.     Center_Dialog( dial ) ;
  1935.     (* First, we need to ensure that the state of various dialog objects
  1936.       matches the state of our internal variables! *)
  1937.     FOR opt := 1 TO max_option DO
  1938.       IF opt IN [ FORGEM,FORTOS,FORACC,ERRPAUSE,CHNLINK,DBGOPT,EDITCOMP,
  1939.                   STKOPT,RNGOPT,CLROPT,BAKOPT,NOCODE ] THEN
  1940.         Obj_SetState( dial, opt, Normal, false ) ;
  1941.     CASE for_gem OF
  1942.       GEM_O        :  Obj_SetState( dial, FORGEM, Selected, false ) ;
  1943.       TOS_O, TTP_O :  Obj_SetState( dial, FORTOS, Selected, false ) ;
  1944.       ACC_O        :  Obj_SetState( dial, FORACC, Selected, false ) ;
  1945.     END ;
  1946.     FOR opt := 1 TO max_option DO
  1947.       IF opt IN [ ERRPAUSE, CHNLINK, DBGOPT, EDITCOMP, STKOPT, RNGOPT,
  1948.         CLROPT, BAKOPT, NOCODE ] THEN
  1949.         IF cmp_opts[ opt ] THEN
  1950.           Obj_SetState( dial, opt, Checked, false ) ;
  1951.     IF cmp_opts[ NOCODE ] THEN BEGIN  (* no object code, so no link *)
  1952.       cmp_opts[ CHNLINK ] := FALSE ;
  1953.       Obj_SetState( dial, CHNLINK, Normal, false ) ;
  1954.       END ;
  1955.     Set_DText( dial, BACKPATH, backup_path, System_Font, TE_Left ) ;
  1956.     button := Do_Dialog( dial, BACKPATH ) ;
  1957.     WHILE (button <> CMPOK) AND (button <> CMPCAN) DO
  1958.       BEGIN
  1959.         IF Obj_State(dial, button) = Normal THEN
  1960.           Obj_SetState( dial, button, Checked, true )
  1961.         ELSE
  1962.           Obj_SetState( dial, button, Normal, true ) ;
  1963.         IF Obj_State(dial, NOCODE) = Checked THEN
  1964.           Obj_SetState( dial, CHNLINK, Normal, true ) ;
  1965.         button := Redo_Dialog( dial, BACKPATH ) ;
  1966.       END ;
  1967.     End_Dialog( dial ) ;
  1968.     Obj_SetState( dial, button, Normal, FALSE ) ;
  1969.     IF button = CMPOK THEN
  1970.       BEGIN
  1971.         FOR opt := 1 TO max_option DO
  1972.           IF opt IN [ ERRPAUSE,CHNLINK,DBGOPT,EDITCOMP,STKOPT,RNGOPT,
  1973.                       CLROPT,BAKOPT,NOCODE ] THEN
  1974.             cmp_opts[ opt ] := Obj_State( dial, opt ) = Checked ;
  1975.         IF Obj_State( dial, FORGEM ) = Selected THEN
  1976.           for_gem := GEM_O ;
  1977.         IF Obj_State( dial, FORTOS ) = Selected THEN
  1978.           for_gem := TOS_O ;
  1979.         IF Obj_State( dial, FORACC ) = Selected THEN
  1980.           for_gem := ACC_O ;
  1981.         Get_DEdit( dial, BACKPATH, backup_path ) ;
  1982.       END ;
  1983.   END ;
  1984.  
  1985.  
  1986.  
  1987. (* Do_Menu - Perform a menu operation which was selected by the user with the
  1988.     mouse.  The chosen menu title and item are passed in the parameters
  1989.     'title' and 'item', respectively. *)
  1990.  
  1991.   FUNCTION Do_Menu( title, item : integer ) : boolean ;
  1992.     VAR
  1993.       done : boolean ;
  1994.     BEGIN
  1995.       done := false ;
  1996.       Wind_Update( BEG_Mctrl ) ; {After the menu selection, stop other menus}
  1997.       CASE item OF               {from popping down and ruining our screen!}
  1998.         MIINFO    : formdo(CONTINFO, NOHIDE);
  1999.         MIEDIT    : Compile_Edit( 1, TRUE ) ;
  2000.         MICOMPIL  : Compile_Edit( 2, TRUE ) ;
  2001.         MILINK    : Call_Linker( TRUE ) ;
  2002.         MIRUN     : Call_Program( TRUE ) ;
  2003.         MICMPOPT  : Compiler_Options ;
  2004.         MILNKOPT  : Link_Options ;
  2005.         MISAVOPT  : Save_Options ;
  2006.         MILOAOPT  : Load_Options ;
  2007.         MISOURCE  : Set_Source ;
  2008.         MILOCATE  : Locate_programs ;
  2009.         MICOPY    : Do_Copy ;
  2010.         MIDLF     : Delete_File ;
  2011.         MICRD     : Create_Folder ;
  2012.         MIDLFOL   : Setup_DFolder ;
  2013.         MICHN     : Rename_File ;
  2014.         MIPRF     : Print_File ;
  2015.         MIDF      : Disk_Space ;
  2016.         MIQUIT    : done := true ;
  2017.       END ;
  2018.       Menu_Normal( menu, title ) ;
  2019.       Do_Menu := done ;
  2020.       IF item<>MIRUN THEN Wind_Update( End_Mctrl ) ;
  2021.     END ;
  2022.     
  2023. {The next series of SHORT procedure run the menu selections from Keypresses}
  2024.     
  2025.   PROCEDURE link ;
  2026.   BEGIN
  2027.     Menu_Hilight( menu, MFILE ) ;
  2028.     Call_Linker( FALSE ) ;
  2029.     Menu_Normal( menu, MFILE ) ;
  2030.   END ;  
  2031.  
  2032.   PROCEDURE run;
  2033.   BEGIN
  2034.     Menu_Hilight( menu, MFILE ) ;
  2035.     Call_Program( FALSE ) ;
  2036.     Menu_Normal( menu, MFILE ) ;
  2037.   END ;  
  2038.  
  2039.   PROCEDURE edit ;
  2040.   BEGIN
  2041.     Menu_Hilight( menu, MFILE ) ;
  2042.     Compile_Edit( 1, FALSE ) ;
  2043.     Menu_Normal( menu, MFILE ) ;
  2044.   END ;  
  2045.  
  2046.   PROCEDURE compile ;
  2047.   BEGIN
  2048.     Menu_Hilight( menu, MFILE ) ;
  2049.     Compile_Edit( 2, FALSE ) ;
  2050.     Menu_Normal( menu, MFILE ) ;
  2051.   END ;  
  2052.  
  2053.   PROCEDURE copyF ;
  2054.   BEGIN
  2055.     Menu_Hilight( menu, MSPECIAL ) ;
  2056.     Do_Copy ;
  2057.   END ;  
  2058.  
  2059.   PROCEDURE rename ;
  2060.   BEGIN
  2061.     Menu_Hilight( menu, MSPECIAL ) ;
  2062.     Rename_File ;
  2063.     Menu_NORMAL( menu, MSPECIAL ) ;
  2064.   END ;  
  2065.  
  2066.   PROCEDURE disk ;
  2067.   BEGIN
  2068.     Menu_Hilight( menu, MSPECIAL ) ;
  2069.     Disk_Space ;
  2070.     Menu_Normal( menu, MSPECIAL ) ;
  2071.   END ;  
  2072.  
  2073.   PROCEDURE print ;
  2074.   BEGIN
  2075.     Menu_Hilight( menu, MSPECIAL ) ;
  2076.     Print_File ;
  2077.     Menu_Normal( menu, MSPECIAL ) ;
  2078.   END ;  
  2079.  
  2080.   PROCEDURE deleteF ;
  2081.   BEGIN
  2082.     Menu_Hilight( menu, MSPECIAL ) ;
  2083.     Delete_File ;
  2084.   END ;  
  2085.  
  2086.   PROCEDURE deleteD ;
  2087.   BEGIN
  2088.     Menu_Hilight( menu, MSPECIAL ) ;
  2089.     Setup_DFolder ;
  2090.   END ;  
  2091.  
  2092.   PROCEDURE createD ;
  2093.   BEGIN
  2094.     Menu_Hilight( menu, MSPECIAL ) ;
  2095.     Create_Folder ;
  2096.     Menu_Normal( menu, MSPECIAL ) ;
  2097.   END ;  
  2098.  
  2099.   PROCEDURE Event_Loop ;
  2100.     VAR
  2101.       what_key,
  2102.       which : integer ;
  2103.       done : boolean ;
  2104.       msg : Message_Buffer ;
  2105.  
  2106.     BEGIN
  2107.       done := FALSE ;
  2108.       REPEAT
  2109.         which := Get_Event( E_keyboard|E_Message, 0, 0, 0, 0,
  2110.                     false, 0, 0, 0, 0, false, 0, 0, 0, 0,
  2111.                     msg, what_key, dummy, dummy, dummy, dummy, dummy ) ;
  2112.         IF which & E_Message <> 0 THEN
  2113.           BEGIN
  2114.            IF msg[0]=MN_Selected THEN done := Do_Menu( msg[3], msg[4] ) ;
  2115.           END 
  2116.         ELSE IF which & E_Keyboard <> 0 THEN
  2117.           BEGIN
  2118.             Wind_Update( Beg_Mctrl ) ;
  2119.             IF what_key = $6100 THEN done := TRUE
  2120.             {Allow control OR ALTERNATE key presses!}
  2121.             ELSE IF (what_key = $1205) OR (what_key = $1200) THEN edit  
  2122.             ELSE IF (what_key = $2E03) OR (what_key = $2E00) THEN compile  
  2123.             ELSE IF (what_key = $260C) OR (what_key = $2600) THEN link  
  2124.             ELSE IF (what_key = $1312) OR (what_key = $1300) THEN run
  2125.             ELSE IF what_key = $3B00 THEN copyF
  2126.             ELSE IF what_key = $3C00 THEN createD
  2127.             ELSE IF what_key = $3D00 THEN rename
  2128.             ELSE IF what_key = $3E00 THEN disk
  2129.             ELSE IF what_key = $3F00 THEN print
  2130.             ELSE IF what_key = $4000 THEN deleteF
  2131.             ELSE IF what_key = $4100 THEN deleteD ;
  2132.             IF (what_key<>$1312) AND (what_key<>$1300) THEN
  2133.               Wind_Update( End_Mctrl ) ;
  2134.           END ;    
  2135.       UNTIL done ;
  2136.     END ;
  2137.  
  2138.  
  2139. FUNCTION Low_Resolution : boolean ;
  2140. BEGIN
  2141.   rez := get_rez ;                (* need to remember screen resolution *)
  2142.   Low_Resolution := (rez = 0) ;
  2143. END ;
  2144.  
  2145.  
  2146. (* main *)
  2147.   BEGIN
  2148.     IF Init_Gem <> -1 THEN
  2149.       BEGIN
  2150.         IF NOT Load_Resource( 'pascalm.rsc' ) THEN
  2151.           dummy := Do_Alert( '[3][PASCALM.RSC not found!][ Cancel ]', 0 )
  2152.         ELSE IF Low_Resolution THEN
  2153.           BEGIN
  2154.             bad_res := '[3][You must use medium or|high resolution to use|';
  2155.             bad_res := ConCat(bad_res, 'Personal Pascal.][ Cancel ]');
  2156.             dummy := Do_Alert(bad_res, 0);
  2157.           END
  2158.         ELSE
  2159.           BEGIN
  2160.             Set_Defaults ;
  2161.             Read_Options( 'PASCALM.INF', FALSE ) ;
  2162.             new( envp ) ;
  2163.             envp^[0] := chr(0) ;
  2164.             Find_Menu( PASMENU, menu ) ;
  2165.             Draw_Menu( menu ) ;
  2166.             Init_Mouse ;
  2167.             formdo( BEGINFO, HIDE ) ;
  2168.             Event_Loop ;
  2169.             Erase_Menu( menu ) ;
  2170.           END ;
  2171.         Exit_Gem ;
  2172.       END ;
  2173.   END .
  2174.   
  2175. (* End of PASCALM.PAS }    
  2176.