home *** CD-ROM | disk | FTP | other *** search
/ C/C++ User's Journal & Wi…eveloper's Journal Tools / C-C__Users_Journal_and_Windows_Developers_Journal_Tools_1997.iso / smxdemo / file / fdemo.c next >
Encoding:
C/C++ Source or Header  |  1993-05-25  |  55.2 KB  |  1,627 lines

  1. /*
  2. * FDEMO.C                                                   Version 2.31
  3. *
  4. * FILEdemo module. Contains code to demonstrate use of smx with smxFile.
  5. *
  6. * Copyright (c) 1993 Micro Digital Associates, Inc. 
  7. *               All Rights Reserved.
  8. *
  9. * Author: Peter Van Oudenaren
  10. *
  11. ***********************************************************************/
  12.  
  13. #define SMX_HEAPS 1
  14.  
  15. #include    "conf.h"
  16. #include    "core.h"
  17. #include    "xmwin.h"
  18. #include    "fdemo.h"
  19. #include    <xfile.h>  /* Also brings in fconf.h */
  20. #include    <stdio.h>  /* Included only for the dos test in xfd_read_test_main */
  21. #include    <fcntl.h>  /* Included only for the dos test in xfd_read_test_main */
  22. //#include    <io.h>     /* Included only for the dos test in xfd_read_test_main */
  23. #include    <conio.h>  /* For prototype of inp and outp */
  24. #include    <time.h>
  25.  
  26. /* function prototypes */
  27.  
  28. #if __cplusplus
  29.  extern "C" {
  30. #endif
  31.  
  32. /* demo tasks */
  33. void _cdecl xfd_cscan_main(void);
  34. void _cdecl xfd_seek_test_main(void);
  35. void _cdecl xfd_read_test_main(void);
  36. void _cdecl xfd_write_test_main(void);
  37. void _cdecl xfd_ascan_main(void);
  38. void _cdecl xfd_prompt_main(void);
  39.  
  40. /* demo task helpers */
  41. void mkname(char *buffer, DSTAT *pstat);
  42. void xfd_write_status(int line, char *message);
  43. void xfd_write_purge(char *subdir);
  44. BOOL xfd_write_rmdir(char *subdir);
  45. void xfd_write_make_files(char *subdir);
  46. void xfd_write_rename_files(char *subdir);
  47. BOOLEAN ram_disk_init(void);
  48. void prompt(int goto_sleep,char *p0, char *p1,char *p2, char *p3, char *p4);
  49. void draw_title(XMWIN_PTR win, char * title, char * buffer);
  50.  
  51. /* control functions */
  52. void _cdecl opcon_main(void);
  53. void create_demo_menu(void);
  54. void command_dispatch(int command);
  55. void set_devtable(void);
  56. void  fdemo_suspend_me(int do_signal);
  57. void _cdecl xfd_error(char *p);
  58.  
  59. /* miscellaneous */
  60. void _cdecl appl_init(void);
  61. char * _cdecl ltoa(long, char *, int);
  62. void _cdecl quit_appl(void);
  63. extern int rand();
  64. void _cdecl show_etime(void);
  65. void swap_screen(void);
  66.  
  67. #if __cplusplus
  68. }
  69. #endif
  70.  
  71. /* variables */
  72.  
  73. unsigned char FGCOLOR;
  74. unsigned char BGCOLOR;
  75. unsigned char MENU_FG;
  76. unsigned char MENU_BG;
  77. unsigned char MENU_GREYED_FG;
  78. unsigned char MENU_GREYED_BG;
  79. unsigned char MENU_HIGH_FG;
  80. unsigned char MENU_HIGH_BG;
  81.  
  82. /* Room to control 10 tasks increase it if needed */
  83. #define MAXDEMOTASKS 5
  84. typedef struct _demo_control {
  85.     TCB_PTR p_task;         /* Task handle */
  86.     char *pause_menu;       /* Menu strings */
  87.     char *resume_menu;
  88.     XMWIN_PTR window;
  89.     /* Flags. Add to these as we need them */
  90.     word    suspended;
  91. } _DEMO_CONTROL;
  92. _DEMO_CONTROL demo_control[MAXDEMOTASKS];
  93. /* Indeces into the above table */
  94. #define DEMO_TASK_CSCAN     0
  95. #define DEMO_TASK_SEEK      1
  96. #define DEMO_TASK_READ      2
  97. #define DEMO_TASK_WRITE     3
  98. #define DEMO_TASK_ASCAN     4
  99.  
  100. XCB_PTR     free_msgs;
  101.  
  102. /* Tasks for the demo */
  103. TCB_PTR     opcon;         /* operation control task (for kbd) */
  104. TCB_PTR xfd_cscan_tcb;     /* Scans the c drive */
  105. TCB_PTR xfd_seek_tcb;      /* Seeks and reads a file on the c drive */
  106. TCB_PTR xfd_read_tcb;      /* Fast reads a file on the c drive */
  107. TCB_PTR xfd_write_tcb;     /* creates/removes files and dirs on a: or ramdisk */
  108. TCB_PTR xfd_ascan_tcb;     /* Scans the a or ram disk */
  109. TCB_PTR xfd_prompt_tcb;    /* Prints friendly mesages */
  110.  
  111. TCB_PTR suspend_this_task; /* If true this task should be suspend next time it
  112.                               exits and unlocks the screen. */
  113.  
  114. /* Windows */
  115. XMWIN_PTR xfd_appl_win   = 0;
  116. XMWIN_PTR xfd_cscan_win  = 0;
  117. XMWIN_PTR xfd_seek_win   = 0;
  118. XMWIN_PTR xfd_read_win   = 0;
  119. XMWIN_PTR xfd_write_win  = 0;
  120. XMWIN_PTR xfd_ascan_win  = 0;
  121. XMWIN_PTR xfd_prompt_win  = 0;
  122.  
  123. /* Window titles */
  124. char * xfd_cscan_df_title  = "SCANNING HARD DRIVE";
  125. char * xfd_seek_df_title   = "SEEK & READ      ";
  126. char * xfd_read_df_title   = "SEQ. READS/10K BUFFER - Suspend other Tasks For Speed";
  127. char * xfd_write_df_title  = "FLOPPY WRITE     ";
  128. char * xfd_ascan_df_title  = "SCANNING FLOPPY  ";
  129.  
  130. /* User help */
  131. unsigned char * non_menu_u_prompt   = "esc to Exit, F1, F2, F3 for menus     ";
  132.                        /* 030 et all are arrow chars */
  133. unsigned char * menu_u_prompt = "\030 \031 \032 \032 Move, ^cr selects, esc cancels";
  134.  
  135. /* Colors */
  136.  
  137. /* Disk info */
  138. char *hd_drive_id  = "C:";
  139. char *fd_drive_id = "A:";
  140.  
  141. static char largest_f_path[EMAXPATH];
  142. unsigned long largest_f_size;
  143.  
  144. /* DEBUGGING AIDS
  145.     These can be sent on the command line */
  146. /* If true use semaphores to control access to the file system otherwise
  147.    use process locks  */
  148. BOOLEAN use_fs_sem =   FALSE;
  149. /* If this is true we copy the bios entry points in to the devtable */
  150. BOOLEAN use_ebs_dev = FALSE;
  151. BOOLEAN force_mono = FALSE;
  152. BOOLEAN force_color = FALSE;
  153.  
  154. /* Control objects */
  155. ECB_PTR first_scan_done;
  156. ECB_PTR suspend_completed;
  157. ECB_PTR go_event;
  158.  
  159.  
  160. /* externals */
  161. extern PXCB_PTR        kbd_pipe;      /* pipe used by keyin() */
  162. extern PXCB_PTR        op_pipe;       /* operation input pipe */
  163.  
  164.  
  165. /* Demo Menus */
  166. #define NMEN 3
  167. SUB_MENU menus[NMEN];
  168. /* Exprot this to the menu package in xmwin.c */
  169. int n_sub_menus = NMEN;
  170.  
  171. /* Pause and resume. commands. The task is encoded */
  172. #define CMD_PAUSE_CSCAN     (0x10|DEMO_TASK_CSCAN)
  173. #define CMD_RESUME_CSCAN    (0x20|DEMO_TASK_CSCAN)
  174. #define CMD_PAUSE_SEEK      (0x10|DEMO_TASK_SEEK)
  175. #define CMD_RESUME_SEEK     (0x20|DEMO_TASK_SEEK)
  176. #define CMD_PAUSE_READ      (0x10|DEMO_TASK_READ)
  177. #define CMD_RESUME_READ     (0x20|DEMO_TASK_READ)
  178. #define CMD_PAUSE_WRITE     (0x10|DEMO_TASK_WRITE)
  179. #define CMD_RESUME_WRITE    (0x20|DEMO_TASK_WRITE)
  180. #define CMD_PAUSE_ASCAN     (0x10|DEMO_TASK_ASCAN)
  181. #define CMD_RESUME_ASCAN    (0x20|DEMO_TASK_ASCAN)
  182. #define CMD_USE_DOS         0x02
  183. #define CMD_USE_D           0x03
  184. #define CMD_USE_B           0x04
  185. #define CMD_USE_RD          0x05
  186. #define CMD_QUIT            0x06
  187. #define CMD_GO              0x07
  188.  
  189. /* For debugging */
  190. void say(char * string)     /* __fn__ */
  191. {
  192.     wr_dbstring(1, 1, FGCOLOR, BGCOLOR, string);
  193. /*     suspend(ct, 36);  */
  194. }
  195. void say_2(char * string)     /* __fn__ */
  196. {
  197.     wr_dbstring(40, 1, FGCOLOR, BGCOLOR, string);
  198. /*     suspend(ct, 36);  */
  199. }
  200.  
  201. /***** APPLICATION INITIALIZATION
  202. *  
  203. * Creates all tasks and initialzes the windowing system
  204. **********************************************************************/
  205.  
  206. void _cdecl appl_init()                             /* __fn__ */
  207. {
  208.     unsigned char buf[2];
  209.     unsigned char video;
  210.     extern BOOLEAN monochrome;
  211.  
  212.     /* If the video memory recognizer has trouble the user may specify M or C
  213.        from the command line */
  214.     if (force_mono)
  215.         op_screen = (word far *)MDA;
  216.     else if (force_color)
  217.         op_screen = (word far *)CGA;
  218.  
  219.     /* Get the video adaptor from CMOS location 0x14 bits 4&5. 0x11 ==s monochrome */
  220.     outp(0x70,0x14|0x80);
  221.     video = inp(0x71);
  222.     
  223.     if ((video & 0x30) == 0x30)
  224.     {
  225.         monochrome = TRUE;
  226.         FGCOLOR = MO_FGCOLOR;
  227.         BGCOLOR = MO_BGCOLOR;
  228.         MENU_FG = MO_MENU_FG;
  229.         MENU_BG = MO_MENU_BG;
  230.         MENU_GREYED_FG = MO_MENU_GREYED_FG;
  231.         MENU_GREYED_BG = MO_MENU_GREYED_BG;
  232.         MENU_HIGH_FG = MO_MENU_HIGH_FG;
  233.         MENU_HIGH_BG = MO_MENU_HIGH_BG;
  234.     }
  235.     else
  236.     {
  237.         FGCOLOR = CO_FGCOLOR;
  238.         BGCOLOR = CO_BGCOLOR;
  239.         MENU_FG = CO_MENU_FG;
  240.         MENU_BG = CO_MENU_BG;
  241.         MENU_GREYED_FG = CO_MENU_GREYED_FG;
  242.         MENU_GREYED_BG = CO_MENU_GREYED_BG;
  243.         MENU_HIGH_FG = CO_MENU_HIGH_FG;
  244.         MENU_HIGH_BG = CO_MENU_HIGH_BG;
  245.     }
  246.  
  247. #if (EBS_IDE && EBS_FLOPPY)
  248.     /* Debugging aid. Use the drivers instead of bios */
  249.     if (use_ebs_dev)
  250.     {
  251.         set_devtable();
  252.     }
  253. #endif
  254.  
  255.    #ifdef CODEVIEW
  256.     opcon = create_task(opcon_main, 0, 0);
  257.    #else
  258.     opcon = create_task(opcon_main, MAX, 0);
  259.    #endif
  260.  
  261.     /* fdemo specific application initialization */
  262.  
  263.     /* xfile needs stime to be set properly so it can date stamp files.
  264.        in this demo we call DOS's time function. to set it */
  265.     _disable();
  266.     time((time_t *) &stime);
  267.     _enable();
  268.  
  269.     /* Create the video windoows for the demo */
  270.     xfd_appl_win   =  xmwin_create( 0,  1, 80, 24, FGCOLOR, BGCOLOR,  XWS_BORDER_DOUBLE|XWS_SAVE_UNDER);
  271.     xfd_prompt_win  = xmwin_create(0,  1, 58, 7, FGCOLOR, BGCOLOR, XWS_BORDER_DOUBLE);
  272.     /* Fix the corner where the two windows intersect */
  273.     buf[0] = 204; buf[1] = 0; wr_ustring(0, 7, FGCOLOR, BGCOLOR,buf);
  274.     xfd_cscan_win  = xmwin_create( 1,  8, 56, 4, FGCOLOR, BGCOLOR, XWS_BORDER_SINGLE);
  275.     xfd_seek_win   = xmwin_create( 1, 12, 56, 4, FGCOLOR, BGCOLOR, XWS_BORDER_SINGLE);
  276.     xfd_read_win   = xmwin_create( 1, 16, 56, 4, FGCOLOR, BGCOLOR, XWS_BORDER_SINGLE);
  277.     xfd_write_win  = xmwin_create( 1, 20, 56, 4, FGCOLOR, BGCOLOR, XWS_BORDER_SINGLE);
  278.     xfd_ascan_win  = xmwin_create(58,  2, 21, 22, FGCOLOR, BGCOLOR, XWS_BORDER_SINGLE);
  279.  
  280.     /* Put up a prompt at the bottom of the screen */
  281.     wr_ustring(1, 24, FGCOLOR, BGCOLOR,non_menu_u_prompt);
  282.     
  283.     /* Create event queues we will use to control our tasks */
  284.     first_scan_done  = create_eq();     /* After the first scan of winchester */
  285.     suspend_completed  = create_eq();   /* Signal by task when it suspends */
  286.     go_event = create_eq();             /* Signal when user presses Run Demos */
  287.  
  288. #define PRIO NORM
  289.     /* Create demo tasks */
  290.     xfd_cscan_tcb  =    create_task(xfd_cscan_main, PRIO, 0);
  291.     xfd_seek_tcb   =    create_task(xfd_seek_test_main, PRIO, 0);
  292.     xfd_read_tcb  =    create_task(xfd_read_test_main, PRIO, 0);
  293.     xfd_write_tcb  =    create_task(xfd_write_test_main, PRIO, 0);
  294.     xfd_ascan_tcb  =    create_task(xfd_ascan_main, PRIO, 0);
  295.     xfd_prompt_tcb  =    create_task(xfd_prompt_main, PRIO, 0);
  296.  
  297.     /* Tasks */
  298.     demo_control[DEMO_TASK_CSCAN].p_task   =   xfd_cscan_tcb;
  299.     demo_control[DEMO_TASK_SEEK].p_task    =   xfd_seek_tcb;
  300.     demo_control[DEMO_TASK_READ].p_task    =   xfd_read_tcb;
  301.     demo_control[DEMO_TASK_WRITE].p_task   =   xfd_write_tcb;
  302.     demo_control[DEMO_TASK_ASCAN].p_task   =   xfd_ascan_tcb;
  303.  
  304.     /* Windows */
  305.     demo_control[DEMO_TASK_CSCAN].window   =   xfd_cscan_win;
  306.     demo_control[DEMO_TASK_SEEK].window    =   xfd_seek_win;
  307.     demo_control[DEMO_TASK_READ].window    =   xfd_read_win;
  308.     demo_control[DEMO_TASK_WRITE].window   =   xfd_write_win;
  309.     demo_control[DEMO_TASK_ASCAN].window   =   xfd_ascan_win;
  310.  
  311.     /* Task menu when running */
  312.     demo_control[DEMO_TASK_CSCAN].pause_menu = "Pause  C Scan";
  313.     demo_control[DEMO_TASK_SEEK].pause_menu = "Pause  Seek Test";
  314.     demo_control[DEMO_TASK_READ].pause_menu = "Pause  Read Test";
  315.     demo_control[DEMO_TASK_WRITE].pause_menu = "Pause  Write Test";
  316.     demo_control[DEMO_TASK_ASCAN].pause_menu = "Pause  A Scan";
  317.  
  318.     /* Task menu when paused */
  319.     demo_control[DEMO_TASK_CSCAN].resume_menu = "Resume  C Scan";
  320.     demo_control[DEMO_TASK_SEEK].resume_menu = "Resume  Seek Test";
  321.     demo_control[DEMO_TASK_READ].resume_menu = "Resume  Read Test";
  322.     demo_control[DEMO_TASK_WRITE].resume_menu = "Resume  Write Test";
  323.     demo_control[DEMO_TASK_ASCAN].resume_menu = "Resume  A Scan";
  324.  
  325.         
  326.     /* Smx probe task names */
  327.     BUILD_HT(opcon, "opcon"); 
  328.     BUILD_HT(xfd_cscan_tcb,"xfd_cscan_tcb");
  329.     BUILD_HT(xfd_seek_tcb,"xfd_seek_tcb");
  330.     BUILD_HT(xfd_read_tcb,"xfd_read_tcb");
  331.     BUILD_HT(xfd_write_tcb,"xfd_write_tcb");
  332.     BUILD_HT(xfd_ascan_tcb,"xfd_ascan_tcb");
  333.  
  334.     /* Pop up the top menu */
  335.     create_demo_menu();
  336.     start(opcon);
  337.     start(xfd_cscan_tcb);
  338.     start(xfd_seek_tcb);
  339.     start(xfd_write_tcb);
  340.     start(xfd_read_tcb);
  341.     start(xfd_ascan_tcb);
  342.     start(xfd_prompt_tcb);
  343. }
  344.  
  345. /***** SUBROUTINES
  346. **********************************************************************/
  347.  
  348. /* DEMO Main Tasks */
  349.  
  350. /* xfd_cscan_main - Walk the file tree
  351.  *
  352.  * This routine walks the directory tree of the file system on the hard disk
  353.  * and displays each directory and file as it is encountered. 
  354.  * It is a bit complicated because it uses its own stack for the traversal.
  355.  * Doing this is safer then writing the routine recurively (which would
  356.  * be simpler). During its first scan it finds the largest file on the system.
  357.  * After the first scan it signals those routines that need to know the largest
  358.  * file. The routine is large but for demo purposes I did not want to break it 
  359.  * up into lots of little routines.
  360.  * See pcls.c in the samples directory for similar information. 
  361.  * xfile calls demonstrated:
  362.  * 
  363.  *       create_file_mgr()
  364.  *       pc_dskopen()
  365.  *       pc_set_default_drive()
  366.  *       pc_set_cwd()
  367.  *       pc_gfirst()
  368.  *       pc_gnext()
  369.  *       pc_gdone()
  370. */
  371. static char cscan_stack[30][13];
  372. BOOLEAN find_largest;
  373.  
  374. void _cdecl xfd_cscan_main(void)                             /* __fn__ */
  375. {
  376. static char display_buffer[80];
  377. static char path[EMAXPATH];
  378. char fname_buffer[14];
  379. DSTAT statobj;
  380. int i,stackp, path_len;
  381. BOOLEAN found_dir;
  382. BOOLEAN display_files;
  383.  
  384.  
  385.     unlock();
  386.  
  387.     draw_title(xfd_cscan_win, xfd_cscan_df_title, display_buffer);
  388.     xmwin_wr_string(xfd_cscan_win, 2, 1, FGCOLOR, BGCOLOR, "Dir :");
  389.     xmwin_wr_string(xfd_cscan_win, 2, 2, FGCOLOR, BGCOLOR, "File:");
  390.     
  391.     /* Wait for the gun */
  392.     count(1, go_event, INF);
  393.  
  394.     /* First register the task as a user of the file manager */
  395.     if (!create_file_mgr())
  396.         xfd_error("xfd_cscan: Can't access file manager");
  397.  
  398.     /* Now mount drive C. */
  399.     if (!pc_dskopen(hd_drive_id))
  400.         xfd_error("xfd_cscan: Can't open hard disk");
  401.  
  402.     /* Set the default drive to C: */
  403.     if (!pc_set_default_drive(hd_drive_id))
  404.         xfd_error("Can't select hard disk as default");
  405.  
  406.     /* Find the largest file on the first pass */
  407.     find_largest = TRUE;
  408.     largest_f_size = 0;
  409.     largest_f_path[0] = '\0';
  410.  
  411.     while(bump_task(ct, ct->priority))
  412.     {   
  413.         /* clear our directory stack */
  414.         for (stackp=0; stackp<30;stackp++) cscan_stack[stackp][0]='\0';
  415.         stackp = 0;
  416.  
  417.         while(bump_task(ct, ct->priority))
  418.         {
  419.             /* Walk up our stack and build a path from it */
  420.             path[0]='\0';
  421.             path_len = 0;
  422.             for (i = 0; i < stackp; i++)   
  423.             { 
  424.                path_len += (strlen(cscan_stack[i])+1); 
  425.                if (path_len > EMAXPATH)
  426.                    xfd_error("Too many subdirs for this build");
  427.                strcat(path,"\\"); 
  428.                strcat(path,cscan_stack[i]);
  429.             }
  430.             if (!stackp)
  431.                 strcat(path,"\\"); 
  432.  
  433.             /* Display files if at a new directory (the stack is NULL for
  434.                this dir. Otherwise we will scan forward til we find where 
  435.                we left */
  436.             if (cscan_stack[stackp][0])
  437.                 display_files = FALSE;
  438.             else
  439.                 display_files = TRUE;
  440.  
  441.             /* Display the path */
  442.             if (display_files)
  443.             {
  444.                 memset(display_buffer,' ', 67);
  445.                 display_buffer[66] = 0;
  446.                 xmwin_wr_string(xfd_cscan_win, 7, 1, FGCOLOR, BGCOLOR,
  447.                                 display_buffer);
  448.                 xmwin_wr_string(xfd_cscan_win, 7, 1, FGCOLOR, BGCOLOR, path);
  449.             }
  450.             /* Set the path to the current working path */
  451.             if (!pc_set_cwd(path))
  452.                 xfd_error("Can't set default directory");
  453.  
  454.             /* Get the first entry in the current working directory */
  455.             found_dir = FALSE;
  456.             if (!pc_gfirst(&statobj, "*.*"))
  457.                 xfd_error("No FIles Found");
  458.             do
  459.             {
  460.                 /* make the directory object into file.nam   */
  461.                 mkname(fname_buffer, &statobj);
  462.  
  463.                 if (statobj.fattribute & ADIRENT)
  464.                 {
  465.                     /* If it's a directory push it on our stack if we haven't
  466.                        visited it yet */
  467.                     if (fname_buffer[0] != '.')
  468.                     {
  469.                         if (!cscan_stack[stackp][0])
  470.                         {
  471.                             strcpy(cscan_stack[stackp],fname_buffer);
  472.                             found_dir = TRUE;
  473.                             break;
  474.                         }
  475.                         else
  476.                         {
  477.                             /* This is the one we just saw. zero the slot
  478.                                so we know to take another one */
  479.                             if (strcmp(cscan_stack[stackp],fname_buffer)==0)
  480.                             {
  481.                                 /* 0 the stack so we take the next directory.
  482.                                    plus display files again */
  483.                                 display_files = TRUE;
  484.                                 cscan_stack[stackp][0] = 0;
  485.                             }
  486.                         }
  487.                     }
  488.                 }
  489.                 else if (!(statobj.fattribute & AVOLUME))
  490.                 {
  491.                     /* It's a file. */
  492.                     /* Display the file */
  493.                     if (display_files)
  494.                     {
  495.                         if (find_largest)
  496.                         {
  497.                             if (statobj.fsize > largest_f_size)
  498.                             {
  499.                                 largest_f_size = statobj.fsize;
  500.                                 strcpy(largest_f_path, path);
  501.                                 if (stackp)
  502.                                     strcat(largest_f_path,"\\"); 
  503.                                 strcat(largest_f_path, fname_buffer); 
  504.                             }
  505.                         }
  506.                         xmwin_wr_string(xfd_cscan_win, 7, 2, FGCOLOR, BGCOLOR, 
  507.                                     "               ");
  508.                         xmwin_wr_string(xfd_cscan_win, 7, 2, FGCOLOR, BGCOLOR, 
  509.                                         fname_buffer);
  510.                     }
  511.                 }
  512.                 bump_task(ct, ct->priority);
  513.             } while (pc_gnext(&statobj));
  514.             /* Call gdone to free up internal resources used by statobj */
  515.             pc_gdone(&statobj);
  516.  
  517.             /* If we found a directory bump the stack pointer */
  518.             if (found_dir)
  519.             {
  520.                 stackp += 1;
  521.                 if (stackp >= 30)
  522.                    xfd_error("Too many subdirs for this build");
  523.                 cscan_stack[stackp][0] = 0;
  524.             }
  525.             else
  526.             {
  527.                 /* Decrement the stack. If already 0 we finished the traverse */
  528.                 if (!stackp)
  529.                     break;
  530.                 /* Clean up the stack and decrement the pointer */
  531.                 cscan_stack[stackp--][0] = 0;
  532.             }
  533.         }
  534.         if (find_largest)
  535.         {
  536.             /* Wake up the read task */
  537.             find_largest = FALSE;
  538.             signal(first_scan_done);
  539.             bump_task(ct, ct->priority);
  540.             /* ungrey all the other tests */
  541.             menus[1].flags[DEMO_TASK_SEEK]    &= ~ITEM_GREYED;
  542.             menus[1].flags[DEMO_TASK_READ]    &= ~ITEM_GREYED;
  543.             menus[1].flags[DEMO_TASK_WRITE]   &= ~ITEM_GREYED;
  544.             menus[1].flags[DEMO_TASK_ASCAN]   &= ~ITEM_GREYED;
  545.         }
  546.     }
  547. }
  548.  
  549. /* xfd_seek_test_main - Randomly seek and read from a large file on the 
  550.  *                      hard disk.
  551.  *
  552.  * This routine waits for scan main to find the largest file on the hard 
  553.  * disk and then opens that file and continuously seeks and reads from it.
  554.  * A graph displays the progress
  555.  * 
  556.  *       create_file_mgr()
  557.  *       pc_dskopen()
  558.  *       pc_set_default_drive()
  559.  *       po_open()
  560.  *       po_read()
  561.  *       po_lseek()
  562.  */
  563.  
  564. void _cdecl xfd_seek_test_main(void)                             /* __fn__ */
  565. {
  566. static unsigned char display_buffer[80];
  567. static unsigned char read_buff[512];
  568. unsigned long blocks_per_tick;
  569. unsigned long largest_f_blocks;
  570. long ltemp;
  571. PCFD fd;
  572. int th_posn = 0;
  573.  
  574.     unlock();
  575.     draw_title(xfd_seek_win, xfd_seek_df_title, display_buffer);
  576.  
  577.     /* Wait for the gun */
  578.     count(1, go_event, INF);
  579.  
  580.     /* Wait for the user to launch it */
  581.     xmwin_wr_string(xfd_seek_win, 1, 1, FGCOLOR, BGCOLOR,
  582.          "Suspended At start up Enable from menus..");
  583.     fdemo_suspend_me(0);
  584.     
  585.  
  586.     memset(display_buffer, ' ', 78);
  587.     display_buffer[78] = 0;
  588.     xmwin_wr_string(xfd_seek_win, 1, 1, FGCOLOR, BGCOLOR, display_buffer);
  589.     
  590.  
  591.     xmwin_wr_string(xfd_seek_win, 1, 1, FGCOLOR, BGCOLOR, "File: ");
  592.     xmwin_wr_string(xfd_seek_win, 7, 1, FGCOLOR, BGCOLOR, largest_f_path);
  593.  
  594.     /* Calculate how to position the thermometer */
  595.     largest_f_blocks = largest_f_size/512;
  596.     blocks_per_tick =   largest_f_blocks/38;
  597.  
  598.     /* Now draw the thermometer with double line chars */
  599.     memset(display_buffer,205, 40);
  600.     display_buffer[0]  = (unsigned char) 204;
  601.     display_buffer[39] = (unsigned char) 185;
  602.     display_buffer[40] = '\0';
  603.     xmwin_wr_string(xfd_seek_win, 4, 2, FGCOLOR, BGCOLOR, display_buffer);
  604.  
  605.     /* First register the task as a user of the file manager */
  606.     if (!create_file_mgr())
  607.         xfd_error("xfd_cscan: Can't access file manager");
  608.  
  609.     /* Make sure drive C is mounted. */
  610.     if (!pc_dskopen(hd_drive_id))
  611.         xfd_error("xfd_cscan: Can't open hard disk");
  612.  
  613.     /* Set the default drive to C: */
  614.     if (!pc_set_default_drive(hd_drive_id))
  615.         xfd_error("Can't select hard disk as default");
  616.  
  617.     /* Open the file */
  618.     if ((fd = po_open(largest_f_path, (PO_BINARY|PO_RDONLY), 0)) < 0)
  619.     {
  620.         xfd_error("Can't open the seek test file");
  621.     }
  622.  
  623.     /* Now randomly seek and read */
  624.     while(bump_task(ct, ct->priority))
  625.     {
  626.         ltemp = (long) rand();
  627.         ltemp %= largest_f_blocks;
  628.         display_buffer[1] = '\0';
  629.         /* Clear the thumb */
  630.         if (th_posn)
  631.         {
  632.             display_buffer[0] = 205;
  633.             xmwin_wr_string(xfd_seek_win, th_posn, 2, FGCOLOR, BGCOLOR, display_buffer);
  634.         }
  635.         if (blocks_per_tick)
  636.         {
  637.             th_posn = (int) (ltemp/blocks_per_tick);
  638.             /* There's a bug in the calculation, fix it here */
  639.             if (th_posn > 37)
  640.                 th_posn = 37;
  641.             th_posn += 5;
  642.             display_buffer[0] = 206;
  643.             xmwin_wr_string(xfd_seek_win, th_posn, 2, FGCOLOR, BGCOLOR, display_buffer);
  644.         }
  645.         
  646.         ltemp *= 512;
  647.         if (po_lseek(fd, ltemp, PSEEK_SET) != ltemp)
  648.             xfd_error("Seek error");
  649.         bump_task(ct, ct->priority);
  650.         if (po_read(fd, read_buff, 512) !=  512)
  651.             xfd_error("Read error");
  652.     }
  653. }
  654.  
  655.  
  656.  
  657. /* xfd_read_test_main - Sequentially read from a large file on the 
  658.  *                      hard disk.
  659.  *
  660.  * This routine waits for scan main to find the largest file on the hard 
  661.  * disk and then opens that file and reads it sequentially. After each
  662.  * read it calulates the throughput.
  663.  * If the user selects it DOS can be used instead of RTFS. This gives an idea
  664.  * of the relative performance of the two.
  665.  * A graph displays the progress
  666.  * 
  667.  *       create_file_mgr()
  668.  *       pc_dskopen()
  669.  *       pc_set_default_drive()
  670.  *       po_open()
  671.  *       po_read()
  672.  *       po_lseek()
  673.  */
  674.  
  675. /* Use 20 blocks per read (10 K) */
  676. #if LARGE_DATA
  677. #define BLOCKS_PREAD 20
  678. #define BYTES_PREAD  (20*512)
  679. #else
  680. #define BLOCKS_PREAD 1
  681. #define BYTES_PREAD  (1*512)
  682. #endif
  683. void _cdecl xfd_read_test_main(void)                             /* __fn__ */
  684. {
  685. static unsigned char display_buffer[80];
  686. char *read_buff;
  687. unsigned long blocks_per_tick;
  688. unsigned long largest_f_blocks;
  689. unsigned long ltemp;
  690. PCFD fd;
  691. int th_posn = 0;
  692. long starting_ticks;
  693.  
  694.     unlock();
  695.     draw_title(xfd_read_win, xfd_read_df_title, display_buffer);
  696.  
  697.     /* Wait for the gun */
  698.     count(1, go_event, INF);
  699.  
  700.     /* Grab a buffer for the test */
  701.     read_buff = (char *) malloc(BYTES_PREAD);
  702.     if (!read_buff)
  703.         xfd_error("Read Test, Not enough core to allocate buffer");
  704.     xmwin_wr_string(xfd_read_win, 1, 1, FGCOLOR, BGCOLOR,
  705.          "Scanning Drive For Largest File....");
  706.  
  707.     /* Wait for the largest file to be found */
  708.     count(1, first_scan_done, INF);
  709.  
  710.     memset(display_buffer, ' ', 78);
  711.     display_buffer[78] = 0;
  712.     xmwin_wr_string(xfd_read_win, 1, 1, FGCOLOR, BGCOLOR, display_buffer);
  713.     
  714.     xmwin_wr_string(xfd_read_win, 1, 1, FGCOLOR, BGCOLOR, "File: ");
  715.     xmwin_wr_string(xfd_read_win, 7, 1, FGCOLOR, BGCOLOR, largest_f_path);
  716.  
  717.     /* Calculate how to position the thermometer */
  718.     largest_f_blocks = largest_f_size/512;
  719.     blocks_per_tick =   largest_f_blocks/38;
  720.  
  721.     /* Now draw the thermometer with double line chars */
  722.     memset(display_buffer,205, 40);
  723.     display_buffer[0]  = (unsigned char) 204;
  724.     display_buffer[39] = (unsigned char) 185;
  725.     display_buffer[40] = '\0';
  726.     xmwin_wr_string(xfd_read_win, 4, 2, FGCOLOR, BGCOLOR, display_buffer);
  727.  
  728.     /* First register the task as a user of the file manager */
  729.     if (!create_file_mgr())
  730.         xfd_error("xfd_cscan: Can't access file manager");
  731.  
  732.     /* Make sure drive C is mounted. */
  733.     if (!pc_dskopen(hd_drive_id))
  734.         xfd_error("xfd_cscan: Can't open hard disk");
  735.  
  736.     /* Set the default drive to C: */
  737.     if (!pc_set_default_drive(hd_drive_id))
  738.         xfd_error("Can't select hard disk as default");
  739.     
  740.     LOCK();
  741.     /* Open the file */
  742.     if ((fd = po_open(largest_f_path, (PO_BINARY|PO_RDONLY), 0)) < 0)
  743.     {
  744.         xfd_error("Can't open the read test file");
  745.     }
  746.     unlock();
  747.     
  748.     strcpy(read_buff,hd_drive_id);
  749.     strcat(read_buff,largest_f_path);
  750.  
  751.  
  752.     /* Now sequentially read */
  753.     ltemp = 0;    
  754.     starting_ticks = get_etime();
  755.  
  756.     while(bump_task(ct, ct->priority))
  757.     {
  758.         if (ltemp == 0)
  759.         draw_title(xfd_read_win, xfd_read_df_title, display_buffer);
  760.  
  761.         ltemp %= largest_f_blocks;
  762.         display_buffer[1] = '\0';
  763.             /* Clear the thumb */
  764.  
  765.         if (th_posn)
  766.         {
  767.             display_buffer[0] = 205;
  768.             xmwin_wr_string(xfd_read_win, th_posn, 2, FGCOLOR, BGCOLOR, display_buffer);
  769.         }
  770.         if (blocks_per_tick)
  771.         {
  772.             th_posn = (int) (ltemp/blocks_per_tick);
  773.             /* There's a bug in the calculation, fix it here */
  774.             if (th_posn > 37)
  775.                 th_posn = 37;
  776.             th_posn += 5;
  777.             display_buffer[0] = 206;
  778.             xmwin_wr_string(xfd_read_win, th_posn, 2, FGCOLOR, BGCOLOR, display_buffer);
  779.         }
  780.         if (po_read(fd, read_buff, BYTES_PREAD) == (UCOUNT) ~0)
  781.             xfd_error("Read error");
  782.  
  783.         ltemp += BLOCKS_PREAD;    
  784.         if (ltemp >= largest_f_blocks)
  785.         {
  786.             if (po_lseek(fd, 0L, PSEEK_SET) != 0L)
  787.                 xfd_error("Seek error");
  788.            
  789.             /* Calculate transfer rate */
  790.             /* Elapsed time in seconds */
  791.             ltemp = get_etime()-starting_ticks;
  792.             /* Bytes/second */
  793.             if (ltemp)
  794.                 ltemp = ((largest_f_blocks*512)/ltemp)*SEC;
  795.             else
  796.                 ltemp = 0;
  797.  
  798.             /* Clear the line and write the transfer rate */
  799.             memset(display_buffer, ' ', 78);
  800.             display_buffer[78] = 0;
  801.             xmwin_wr_string(xfd_read_win, 1, 1, FGCOLOR, BGCOLOR, display_buffer);
  802.             ltoa(ltemp, display_buffer, 10);
  803.             strcat(display_buffer, " Bytes/Second");
  804.             xmwin_wr_string(xfd_read_win, 1, 1, FGCOLOR, BGCOLOR, display_buffer);
  805.  
  806.             /* Remember the time for next time */
  807.             starting_ticks = get_etime();
  808.             /* reset the byte counter. ltemp is really overused, I know */
  809.             ltemp = 0;
  810.         }
  811.     }
  812. }
  813.  
  814. /* xfd_write_test_main - Create directorues and files. Then rename the files,
  815.  *                       delete them and then delete the directories.
  816.  *                      
  817.  * This routine works on the user selected folppy or ram disk. Creates two
  818.  * directories, populates them with files, renames the files, deletes the files
  819.  * and finally deletes the directories. This loops continuosly. Its sister
  820.  * function xfd_ascan_main() scans these directories and prints the tree 
  821.  * structure in a continuous manner.
  822.  * 
  823.  *       create_file_mgr()
  824.  *       pc_dskopen()
  825.  *       pc_set_default_drive()
  826.  *       pc_mkfs() - See ram_disk_init()
  827.  *       po_open()
  828.  *       po_read()
  829.  *       po_close()
  830.  *       po_mkdir()
  831.  *       po_rmdir()
  832.  *       pc_set_cwd()
  833.  *       pc_iddir()
  834.  *       pc_mv()
  835.  *       po_unlink()
  836.  * 
  837.  *  To do all this in line would have been unwieldly, so several helper functions
  838.  *  were created. See the task helper function section after the main tasks.
  839.  *
  840.  */
  841.  
  842. /* used by write_test and its helpers */
  843. static char wr_display_buffer[80];
  844. static char wr_display_buffer_2[80];
  845.  
  846. void _cdecl xfd_write_test_main(void)                             /* __fn__*/
  847. {
  848. static char dir[14];
  849. char c;
  850. extern PFILE_SYSTEM_USER fs_user;    /* Current user pointer contains errno/pwd */
  851.  
  852.     unlock();
  853.     draw_title(xfd_write_win, xfd_write_df_title, wr_display_buffer);
  854.     /* Wait for the gun */
  855.     count(1, go_event, INF);
  856.  
  857.  
  858.     /* First register the task as a user of the file manager */
  859.     if (!create_file_mgr())
  860.         xfd_error("xfd_cscan: Can't access file manager");
  861.     if (fd_drive_id[0] == 'E')
  862.         if (!ram_disk_init())
  863.             xfd_error("No Ram drive");
  864.     /* Now mount drive A:. */
  865.     if (!pc_dskopen(fd_drive_id))
  866.         xfd_error("xfd_write: Can't open floppy drive");
  867.     /* Set the default drive to A: */
  868.     if (!pc_set_default_drive(fd_drive_id))
  869.         xfd_error("Can't select floppy as default");
  870.     if (!pc_set_cwd("\\"))
  871.         xfd_error("Can't set default directory");
  872.     /* Wait for the user to enable floppy operations */
  873.     xmwin_wr_string(xfd_write_win, 1, 1, FGCOLOR, BGCOLOR,
  874.          "Suspended At start up Enable from menus..");
  875.     fdemo_suspend_me(0);
  876.  
  877.  
  878.     memset(wr_display_buffer,' ', 67);
  879.     xmwin_wr_string(xfd_write_win, 1, 1, FGCOLOR, BGCOLOR, wr_display_buffer);
  880.     xmwin_wr_string(xfd_write_win, 1, 2, FGCOLOR, BGCOLOR, wr_display_buffer);
  881.  
  882.     strcpy(dir, "SUBDIR1");
  883.  
  884.     while(bump_task(ct, ct->priority))
  885.     {   
  886.         /* Set the default path to \\ */
  887.         if (!pc_set_cwd("\\"))
  888.             xfd_error("Can't set default directory");
  889.         /* Delete all files in two subdirectories and the dirs themselves */
  890.         for (c = '1'; c < '3'; c++)
  891.         {
  892.             dir[6] = c;         /* Flip from SUBDIR1 to SUBDIR2 */
  893.             if (pc_isdir(dir))
  894.             {
  895.                 /* Delete all files from dir */
  896.                 xfd_write_purge(dir);
  897.                 strcpy(wr_display_buffer_2, "Removing: ");
  898.                 strcat(wr_display_buffer_2,  dir);
  899.                 xfd_write_status(1, wr_display_buffer_2);
  900.                 /* Call special rmdir routine which waits around for the
  901.                    scanner routine to stop looking at the directory.
  902.                    Normally you would just call pc_rmdir(dir). It would
  903.                    fail if someone else was using it (which is the
  904.                    correct behavior) */
  905.                 if (!xfd_write_rmdir(dir))
  906.                     xfd_error("Can't remove directory");
  907.             }
  908.         }
  909.  
  910.         /* Create the subdirectory and files */
  911.         xfd_write_status(1, "Creating SUBDIR 1");
  912.         if (!pc_mkdir("SUBDIR1"))
  913. cant_mkdir:
  914.             xfd_error("Can't create directory");
  915.  
  916.         xfd_write_status(1, "Creating SUBDIR 2");
  917.         if (!pc_mkdir("SUBDIR2"))
  918.             goto cant_mkdir;
  919.         
  920.         /* Create a bunch of files */
  921.         xfd_write_make_files("SUBDIR1");
  922.         xfd_write_make_files("SUBDIR2");
  923.         xfd_write_rename_files("SUBDIR1");
  924.         xfd_write_rename_files("SUBDIR2");
  925.     }
  926. }
  927.  
  928. /* xfd_ascan_main - Scan directories and files on the floppy or ram disk.
  929.  *                      
  930.  * This routine works on the user selected floppy or ram disk. It scans for
  931.  * the two directories created by xfd_write_test_main() and print their
  932.  * contents. The display will vary ofer time as the directory contents
  933.  * change.
  934.  * 
  935.  *       create_file_mgr()
  936.  *       pc_dskopen()
  937.  *       pc_set_default_drive()
  938.  *       pc_set_cwd()
  939.  *       pc_isdir()
  940.  *       pc_gfirst()
  941.  *       pc_gnext()
  942.  *       po_gdone()
  943.  * 
  944.  */
  945.  
  946. void _cdecl xfd_ascan_main(void)                                /* __fn__*/
  947. {
  948. static char display_buffer[80];
  949. DSTAT statobj;
  950. int i, posn;
  951. int n_found;
  952.  
  953.     unlock();
  954.  
  955.     draw_title(xfd_ascan_win, xfd_ascan_df_title, display_buffer);
  956.  
  957.     /* Wait for the gun */
  958.     count(1, go_event, INF);
  959.  
  960.     /* First register the task as a user of the file manager */
  961.     if (!create_file_mgr())
  962.         xfd_error("Lost File manager");
  963.  
  964.     if (fd_drive_id[0] == 'E')
  965.         if (!ram_disk_init())
  966.             xfd_error("No Ram drive");
  967.  
  968.     /* Now mount drive A:. */
  969.     if (!pc_dskopen(fd_drive_id))
  970.         xfd_error("No floppy drive");
  971.  
  972.     /* Set the default drive to A: */
  973.     if (!pc_set_default_drive(fd_drive_id))
  974.         xfd_error("Can't set drive");
  975.  
  976.     /* Set the default path to \\ */
  977.     if (!pc_set_cwd("\\"))
  978.         xfd_error("Can't set dir");
  979.  
  980.  
  981.     xmwin_wr_string(xfd_ascan_win, 1, 1, FGCOLOR, BGCOLOR, "Suspended At");
  982.     xmwin_wr_string(xfd_ascan_win, 1, 2, FGCOLOR, BGCOLOR, "Start up..");
  983.     /* Wait to be turned on */
  984.     fdemo_suspend_me(0);
  985.  
  986.     while(bump_task(ct, ct->priority))
  987.     {   
  988.         /* Clear the window */
  989.         memset(display_buffer,' ', 20);
  990.         for (i = 1; i < xfd_ascan_win->height-2; i++)
  991.             xmwin_wr_string(xfd_ascan_win, 1, i, FGCOLOR, BGCOLOR, display_buffer);
  992.  
  993.          posn = 0;
  994.          n_found = 0;
  995.  
  996.         /* See if the DIR exists. If it does we scan through it and display
  997.            its contents */
  998.         if (pc_isdir("SUBDIR1"))
  999.         {
  1000.             posn += 1;
  1001.             n_found += 1;
  1002.  
  1003.             xmwin_wr_string(xfd_ascan_win, 1, posn++, FGCOLOR, BGCOLOR,"SUBDIR1");
  1004.             if (pc_gfirst(&statobj, "SUBDIR1\\*.*"))
  1005.             {
  1006.                 /* Limit the display to for files */
  1007.                 for (i = 1; i < ((xfd_ascan_win->height-4)/2); i++,posn++)
  1008.                 {
  1009.                     /* make the directory object into file.nam   */
  1010.                     mkname(display_buffer, &statobj);
  1011.                     xmwin_wr_string(xfd_ascan_win, 4, posn, FGCOLOR,
  1012.                                     BGCOLOR, display_buffer);
  1013.                     if (!pc_gnext(&statobj))
  1014.                         break;
  1015.                 }
  1016.                 /* Call gdone to free up internal resources used by statobj */
  1017.                 pc_gdone(&statobj);
  1018.             }
  1019.         }
  1020.         /* Repeat the loop for subdir2 */
  1021.         if (pc_isdir("SUBDIR2"))
  1022.         {
  1023.             posn += 1;
  1024.             n_found += 1;
  1025.             xmwin_wr_string(xfd_ascan_win, 1, posn++, FGCOLOR, BGCOLOR,"SUBDIR2");
  1026.             if (pc_gfirst(&statobj, "SUBDIR2\\*.*"))
  1027.             {
  1028.                 for (i = 1; i < ((xfd_ascan_win->height-4)/2); i++,posn++)
  1029.                 {
  1030.                     /* make the directory object into file.nam   */
  1031.                     mkname(display_buffer, &statobj);
  1032.                     xmwin_wr_string(xfd_ascan_win, 4, posn, FGCOLOR,
  1033.                                     BGCOLOR, display_buffer);
  1034.                     if (!pc_gnext(&statobj))
  1035.                         break;
  1036.                 }
  1037.                 /* Call gdone to free up internal resources used by statobj */
  1038.                 pc_gdone(&statobj);
  1039.             }
  1040.         }
  1041.         /* Suspend a few ticks. This smooths thing out a little plus
  1042.            it masks a bug:
  1043.             If this routine did not find any files and we did not suspend
  1044.             smx doesn't preempt us and it spins in a tight loop. Will
  1045.             use probe to find out why later. */
  1046.         suspend(ct,5);
  1047.     }
  1048. }
  1049.  
  1050. /* This task manages the prompt window, There are now xfile calls in it */
  1051.  
  1052. void _cdecl xfd_prompt_main(void)              /* __fn__*/
  1053. {
  1054.     unlock();
  1055.  
  1056.     prompt(0, "              Welcome To The smxFile Demo        ", 
  1057.               "        Use the Options Menu to Modify Parameters",
  1058.               "        Then select Run Demo From The Files Menu",
  1059.               "        Wait for first scan before selecting F2",
  1060.               "           Press Escape at any time to Exit");
  1061. #if 0
  1062.     xmwin_scroll(xfd_prompt_win; TRUE);
  1063.     xmwin_scroll(xfd_prompt_win; FALSE);
  1064. #endif
  1065.  
  1066.     /* Wait for the gun */
  1067.     count(1, go_event, INF);
  1068.     while(bump_task(ct, ct->priority))
  1069.     {
  1070.         prompt(1,"   There are five tasks running, each performing",
  1071.                  "   a different function. The first continually scans",
  1072.                  "   the hard drive and prints the names of all files",
  1073.                  "   and directories.",0);
  1074.         prompt(1," The second task waits for the first scan of the disk",
  1075.                  " to complete and then randomly seeks and reads from",
  1076.                  " the largest file on it. This task is initially disabled",
  1077.                  " for max thruput. The third task reads the largest file",
  1078.                  " sequentially and calculates disk thruput.");
  1079.         prompt(1," The fourth task creates two directories on the floppy",
  1080.                  " or RAM disk and fills them with files which are",
  1081.                  " later renamed and deleted. The fifth task continually",
  1082.                  " scans the floppy disk and displays the contents of",
  1083.                  " the two directories.");
  1084.         prompt(1," The Floppy tasks are disabled at first because",
  1085.                  " they slow down the hard disk tasks. It\'s the fault",
  1086.                  " of the BIOS not smxFile. We have drivers to fix this.",
  1087.                  " You may enable floppy tasks from the F2 menu. Be sure",
  1088.                  " to use a high density floppy.");
  1089.         prompt(1," If you want something a little snappier, you may use",
  1090.                  " a RAM disk instead of a floppy disk for the \"Floppy",
  1091.                  " Tests\". To do this use the F3 options menu before",
  1092.                  " you select Run Demo from the F1 menu.", 0);
  1093.         prompt(1," The \"Read Test\" demonstrates the throughput of",
  1094.                  " smxFile. With some disk controllers the DOS driver is",
  1095.                  " faster than the BIOS driver. Hence the BIOS driver may",
  1096.                  " lower the performance of smxFile relative to DOS.",0);
  1097.         prompt(1," To get a better idea of smxFile performance, invoke",
  1098.                  " this demo with the smx floppy and ide drivers.",
  1099.                  " e.g.: \"run l d\"",0,0);
  1100.     }
  1101. }
  1102.  
  1103. /* Task helper functions */
  1104.  
  1105. /* make a directory object into file.nam   */
  1106. void mkname(char *buffer, DSTAT *pstat)                             /* __fn__ */
  1107. {
  1108. char *pfr, *pto;
  1109.     pto = buffer;  pfr = (char *) pstat->fname;
  1110.     while (*pfr && *pfr!=' ') *pto++ = *pfr++;
  1111.     pfr = pstat->fext;
  1112.     if (*pfr != ' ')  *pto++ = '.';
  1113.     while (*pfr && *pfr!=' ') *pto++ = *pfr++;
  1114.     *pto = '\0';
  1115. }
  1116.  
  1117. /* These routines are helpers to  xfd_write_test_main(void) below */
  1118.  
  1119. void xfd_write_status(int line, char *message)              /* __fn__*/
  1120. {
  1121.     memset(wr_display_buffer,' ', 67);
  1122.     xmwin_wr_string(xfd_write_win, 1, line, FGCOLOR, BGCOLOR, wr_display_buffer);
  1123.     /* If status 1 has change clear status 2 */
  1124.     if (line == 1)
  1125.         xmwin_wr_string(xfd_write_win, 1, 2, FGCOLOR, BGCOLOR, wr_display_buffer);
  1126.     xmwin_wr_string(xfd_write_win, 1, line, FGCOLOR, BGCOLOR, message);
  1127. }
  1128.  
  1129. /* Delete all files in a subdirectory */
  1130. void xfd_write_purge(char *subdir)                              /* __fn__*/
  1131. {
  1132.     DSTAT statobj;
  1133.     BOOL  more;
  1134.     int i;
  1135.     char fname_buffer[14];    
  1136.     BOOL deleted;
  1137.     extern PFILE_SYSTEM_USER fs_user;    /* Current user pointer contains errno/pwd */
  1138.  
  1139.     strcpy(wr_display_buffer_2,"Deleting Files In: ");
  1140.     strcat(wr_display_buffer_2,subdir);
  1141.     xfd_write_status(1, wr_display_buffer_2);
  1142.  
  1143.     if (!pc_set_cwd(subdir))
  1144.         goto cant_set;
  1145.  
  1146.     if (pc_gfirst(&statobj, "*.*"))
  1147.     {
  1148.         do {
  1149.             if (!(statobj.fattribute & ADIRENT))
  1150.             {
  1151.                 mkname(fname_buffer, &statobj);
  1152.                 strcpy(wr_display_buffer_2,"Deleting : ");
  1153.                 strcat(wr_display_buffer_2,fname_buffer);
  1154.                 xfd_write_status(2, wr_display_buffer_2);
  1155.                 /* Get next so the DROJ is no longer open */
  1156.                 more = pc_gnext(&statobj);
  1157.                 if (!more)
  1158.                     pc_gdone(&statobj);
  1159.                 /* xfd_ascan_main is continually scanning the FLOPPY disk. 
  1160.                    If it happens to be looking at this file at the time we try 
  1161.                    to delete it this routine will fail (correctly) with 
  1162.                    fs_user->p_errno == PEACCES. So we suspend and try again
  1163.                    later in this case.
  1164.  
  1165.                    Note:
  1166.                         PEACCES has other meanings as well so we we time out 
  1167.                         after a few. (this is a minor bug in the API)
  1168.                 */
  1169.                 for (i = 0; i < 100; i++)
  1170.                 {
  1171.                     deleted = pc_unlink(fname_buffer);
  1172.                     if (deleted || (fs_user->p_errno != PEACCES))
  1173.                         break;
  1174.                     else
  1175.                         suspend(ct,1);
  1176.                 }
  1177.                 if (!deleted)
  1178.                     xfd_error("Can't delete File");
  1179.             }
  1180.             else
  1181.             {
  1182.                 more = pc_gnext(&statobj);
  1183.                 if (!more)
  1184.                     pc_gdone(&statobj);
  1185.             }
  1186.         } while (more);
  1187.     }
  1188.     if (!pc_set_cwd("\\"))
  1189. cant_set:
  1190.         xfd_error("Can't set default directory");
  1191. }
  1192.  
  1193.  
  1194. /* Remove a subdirectory, bearing in mind that it may be being accessed
  1195.    by the scanner task.  */
  1196. BOOL xfd_write_rmdir(char *subdir)                              /* __fn__*/
  1197. {
  1198.     int i;
  1199.     BOOL deleted;
  1200.     extern PFILE_SYSTEM_USER fs_user;    /* Current user pointer contains errno/pwd */
  1201.  
  1202.     for (i = 0; i < 100; i++)
  1203.     {
  1204.      /* xfd_ascan_main is continually scanning the FLOPPY disk. 
  1205.         If it happens to be looking at this directory at the time we try 
  1206.         to delete it this routine will fail (correctly) with 
  1207.         fs_user->p_errno == PEACCES. So we suspend and try again
  1208.         later in this case.
  1209.          Note:
  1210.              PEACCES has other meanings as well so we we time out 
  1211.               after a few. (this is a minor bug in the API)
  1212.      */
  1213.  
  1214.         deleted = pc_rmdir(subdir);
  1215.         if (deleted || (fs_user->p_errno != PEACCES))
  1216.             break;
  1217.         else
  1218.             suspend(ct,1);
  1219.     }
  1220.     return (deleted);
  1221. }
  1222.  
  1223.  
  1224. /* Create files in a subdirectory */
  1225. void xfd_write_make_files(char *subdir)                           /* __fn__*/
  1226. {
  1227.     int i;
  1228.     int fd;
  1229.     char fname_buffer[14];    
  1230.     char c;
  1231.  
  1232.     strcpy(wr_display_buffer_2,"Creating Files In: ");
  1233.     strcat(wr_display_buffer_2,subdir);
  1234.     xfd_write_status(1, wr_display_buffer_2);
  1235.  
  1236.     if (!pc_set_cwd(subdir))
  1237.         goto cant_set;
  1238.     strcpy(fname_buffer, "FILE_1.TXT");
  1239.  
  1240.     
  1241.     for (i = 0, c = '1'; i < 8; i++, c++)
  1242.     {
  1243.         fname_buffer[5] = c;
  1244.         strcpy(wr_display_buffer_2,"Creating : ");
  1245.         strcat(wr_display_buffer_2,fname_buffer);
  1246.         xfd_write_status(2, wr_display_buffer_2);
  1247.         if ((fd = po_open(fname_buffer,(PO_BINARY|PO_WRONLY|PO_CREAT|PO_TRUNC),
  1248.                                        (PS_IWRITE | PS_IREAD) ) ) < 0)
  1249.                 xfd_error("Can't open File");
  1250.         if (po_write(fd, fname_buffer, 10) != 10)
  1251.                 xfd_error("Can't write File");
  1252.         po_close(fd);
  1253.     }
  1254.  
  1255.     if (!pc_set_cwd("\\"))
  1256. cant_set:
  1257.         xfd_error("Can't set default directory");
  1258. }
  1259.  
  1260. /* Rename files in a directory */
  1261. void xfd_write_rename_files(char *subdir)                       /* __fn__*/
  1262. {
  1263.     DSTAT statobj;
  1264.     BOOL  more;
  1265.     char fname_buffer[14];    
  1266.  
  1267.     strcpy(wr_display_buffer_2,"Renaming Files In: ");
  1268.     strcat(wr_display_buffer_2,subdir);
  1269.     xfd_write_status(1, wr_display_buffer_2);
  1270.  
  1271.     if (!pc_set_cwd(subdir))
  1272.         goto cant_set;
  1273.  
  1274.     if (pc_gfirst(&statobj, "*.*"))
  1275.     {
  1276.         do {
  1277.             if (!(statobj.fattribute & ADIRENT))
  1278.             {
  1279.                 mkname(&fname_buffer[1], &statobj);
  1280.                 strcpy(wr_display_buffer_2,"Rename : ");
  1281.                 strcat(wr_display_buffer_2,&fname_buffer[1]);
  1282.                 xfd_write_status(2, wr_display_buffer_2);
  1283.                 fname_buffer[0] = '_';
  1284.                 /* Get next so the DROJ is no longer open */
  1285.                 more = pc_gnext(&statobj);
  1286.                 if (!pc_mv(&fname_buffer[1],fname_buffer))
  1287.                     xfd_error("Can't rename File");
  1288.             }
  1289.             else
  1290.                 more = pc_gnext(&statobj);
  1291.         } while (more);
  1292.         /* Call gdone to free up internal resources used by statobj */
  1293.         pc_gdone(&statobj);
  1294.     }
  1295.     if (!pc_set_cwd("\\"))
  1296. cant_set:
  1297.         xfd_error("Can't set default directory");
  1298. }
  1299.  
  1300. /* Format a ram disk */
  1301. BOOLEAN ram_disk_init()                                 /* __fn__*/
  1302. {
  1303. IMPORT _PC_BDEVSW pc_bdevsw[];
  1304. FMTPARMS fmt;
  1305. int driveno;
  1306. static BOOLEAN ram_disk_formatted = FALSE;
  1307.  
  1308.     LOCK();
  1309.  
  1310.     if (ram_disk_formatted)
  1311.         goto out;
  1312.  
  1313.     
  1314.     driveno = 4;        /* E: */
  1315.     strcpy(&fmt.oemname[0], "EBS");
  1316.     fmt.secpalloc =      (UTINY)  1;
  1317.     fmt.secreserved =    (UCOUNT) 1;
  1318.     fmt.numfats     =    (UTINY)  1;
  1319.     fmt.secpfat     =    (UCOUNT) 1;
  1320.     fmt.numroot     =    (UCOUNT) 16;   /* One block */
  1321.     fmt.mediadesc =      (UTINY)  0xFD;
  1322.  
  1323.     /* 2 * 2 * (N/4)  =s N */
  1324.     fmt.secptrk     =    (UCOUNT) NRAMDISKBLOCKS/4;
  1325.     fmt.numhead     =    (UCOUNT) 2;
  1326.     fmt.numcyl     =     (UCOUNT) 2;
  1327.     fmt.physical_drive_no =   0;
  1328.     fmt.binary_volume_label = 0x12345678L;
  1329.     strcpy(fmt.text_volume_label, "VOLUMELABE"); 
  1330.  
  1331.     if (!pc_bdevsw[driveno].open_proc(driveno))
  1332.         goto out;
  1333.  
  1334.     /* How many sectors do we need for the fat */
  1335.     fmt.secpfat = pc_fat_size( (UCOUNT) fmt.secreserved,
  1336.                                (UCOUNT) fmt.secpalloc,
  1337.                                (UCOUNT) fmt.numfats,
  1338.                                (UCOUNT) fmt.numroot,NRAMDISKBLOCKS);
  1339.  
  1340.     if (!pc_mkfs(driveno, &fmt ))
  1341.         goto out;
  1342.     ram_disk_formatted = TRUE;
  1343. out:
  1344.     unlock();
  1345.     return(ram_disk_formatted);
  1346. }
  1347.  
  1348. /* Used by prompt_main. This routine displays strings in the prompt window
  1349.    and sleeps if requested. */
  1350.  
  1351. void prompt(int goto_sleep,char *p0, char *p1,char *p2, char *p3, char *p4)/*__fn__*/
  1352. {
  1353. int posn;
  1354. static char display_buffer[80];
  1355.  
  1356.     /* Clear the rows */
  1357.         memset(display_buffer,' ', 79);
  1358.         for (posn = 1; posn < 6; posn++)
  1359.           xmwin_wr_string(xfd_prompt_win, 1, posn, FGCOLOR, BGCOLOR,display_buffer);
  1360.  
  1361.        if (p0)
  1362.            xmwin_wr_string(xfd_prompt_win, 1, 1, FGCOLOR, BGCOLOR,p0);
  1363.        if (p1)
  1364.            xmwin_wr_string(xfd_prompt_win, 1, 2, FGCOLOR, BGCOLOR,p1);
  1365.        if (p2)
  1366.            xmwin_wr_string(xfd_prompt_win, 1, 3, FGCOLOR, BGCOLOR,p2);
  1367.        if (p3)
  1368.            xmwin_wr_string(xfd_prompt_win, 1, 4, FGCOLOR, BGCOLOR,p3);
  1369.        if (p4)
  1370.            xmwin_wr_string(xfd_prompt_win, 1, 5, FGCOLOR, BGCOLOR,p4);
  1371.        if (goto_sleep)
  1372.            suspend(ct, 12*SEC);
  1373. }
  1374. /* Draws a title in top left corner of a window */
  1375. void draw_title(XMWIN_PTR win, char * title, char * buffer)     /* __fn__ */
  1376. {
  1377. char *p = buffer;
  1378.  
  1379.     memset(buffer, CH_SHOR, 76);
  1380.     buffer[75] = 0;
  1381.     while (*title)
  1382.         *p++ = *title++;
  1383.     xmwin_wr_string(win, 1, 0, FGCOLOR, BGCOLOR, buffer);
  1384. }
  1385.  
  1386. /* Task control and interaction functions */
  1387.  
  1388. /***** OPERATION CONTROL
  1389. * Filters key board input and exits or pops up menus
  1390. **********************************************************************/
  1391. void _cdecl opcon_main(void)                             /* __fn__ */
  1392. {
  1393.    char  key;
  1394.    unsigned int  ikey;
  1395.  
  1396.     while(key = (char)(ikey = pget_char(op_pipe, INF)))
  1397.     {
  1398.         if(key == Esc)
  1399.             start(exitx);
  1400.         else if ( (ikey &0xff) == KEY_F1)
  1401.             command_dispatch(process_menu(0));
  1402.         else if ( (ikey &0xff) == KEY_F2)
  1403.             command_dispatch(process_menu(1));
  1404.         else if ( (ikey &0xff) == KEY_F3)
  1405.             command_dispatch(process_menu(2));
  1406.         else if(key == Ctrl_S)
  1407.         {
  1408.             if(sp_scrn_sel)
  1409.                 swap_screen();
  1410.             kbd_pipe = op_pipe;
  1411.         }
  1412.     }
  1413. }
  1414.  
  1415. /* This routine is called to create the menu system for the demo */
  1416. void create_demo_menu()                                      /* __fn__ */
  1417. {
  1418.     menus[0].top = "F1: Files";
  1419.     menus[1].top = "F2: Tasks";
  1420.     menus[2].top = "F3: Options";
  1421.  
  1422.     menus[0].texts[0]    = "Run Demos";
  1423.     menus[0].commands[0] = CMD_GO;
  1424.     menus[0].flags[0]    = 0;
  1425.     menus[0].texts[1]    = "Quit";
  1426.     menus[0].commands[1] = CMD_QUIT;
  1427.     menus[0].flags[1]    = 0;
  1428.     menus[0].texts[2]    = 0;
  1429.  
  1430.     /* Task menu */
  1431.     menus[1].texts[0]    = demo_control[DEMO_TASK_CSCAN].pause_menu;
  1432.     menus[1].commands[0] = CMD_PAUSE_CSCAN;
  1433.     menus[1].flags[0]    = ITEM_GREYED;
  1434.  
  1435.     /* The next group of tasks start in a paused state */
  1436.     menus[1].texts[1]    = demo_control[DEMO_TASK_SEEK].resume_menu;
  1437.     menus[1].commands[1] = CMD_RESUME_SEEK;
  1438.     menus[1].flags[1]    = ITEM_GREYED;
  1439.  
  1440.     /* Read has a delayed start but its starting state is on */
  1441.     menus[1].texts[2]    = demo_control[DEMO_TASK_READ].pause_menu;
  1442.     menus[1].commands[2] = CMD_PAUSE_READ;
  1443.     menus[1].flags[2]    = ITEM_GREYED;
  1444.  
  1445.     menus[1].texts[3]    = demo_control[DEMO_TASK_WRITE].resume_menu;
  1446.     menus[1].commands[3] = CMD_RESUME_WRITE;
  1447.     menus[1].flags[3]    = ITEM_GREYED;
  1448.  
  1449.     menus[1].texts[4]    = demo_control[DEMO_TASK_ASCAN].resume_menu;
  1450.     menus[1].commands[4] = CMD_RESUME_ASCAN;
  1451.     menus[1].flags[4]    = ITEM_GREYED;
  1452.  
  1453.     menus[1].texts[5]    = 0;
  1454.  
  1455.     /* Menus 2 Options. */
  1456.     menus[2].texts[0]    = "Use D: drive Instead of C:";
  1457.     menus[2].commands[0] = CMD_USE_D;
  1458.     menus[2].flags[0]    = 0;
  1459.     menus[2].texts[1]    = "Use B: drive Instead of A:";
  1460.     menus[2].commands[1] = CMD_USE_B;
  1461.     menus[2].flags[1]    = 0;
  1462.     menus[2].texts[2]    = "Use Ram Disk Instead Of Floppy";
  1463.     menus[2].commands[2] = CMD_USE_RD;
  1464.     menus[2].flags[2]    = 0;
  1465. #if 0
  1466.     menus[2].texts[3]    = "Use DOS For Read Performance Test   ";
  1467.     menus[2].commands[3] = CMD_USE_DOS;
  1468.     menus[2].flags[3]    = 0;
  1469.     menus[2].texts[4]    = 0;
  1470. #else
  1471.     menus[2].texts[3]    = 0;
  1472. #endif
  1473.     build_menu();
  1474.     display_top();
  1475. }
  1476.  
  1477. /* This routine is called do dispatch commands from the menus */
  1478. void command_dispatch(int command)                             /* __fn__ */
  1479. {
  1480.     if (!command)
  1481.         return;
  1482.    
  1483.     switch(command)
  1484.     {
  1485.         case CMD_GO:
  1486.             /* Start the process. Grey out start-up items. */
  1487. /*GO*/      menus[0].flags[0]    = 
  1488. /*D:B:&E:*/ menus[2].flags[0]    = 
  1489.             menus[2].flags[1]    = 
  1490.             menus[2].flags[2]    =  ITEM_GREYED;
  1491. /* pause C: */ menus[1].flags[0]    &=  ~ITEM_GREYED;
  1492.  
  1493.             signal(go_event);
  1494.             break;
  1495.         case CMD_QUIT:
  1496.             start(exitx);
  1497.             break;
  1498.         case CMD_USE_D:
  1499.             hd_drive_id  = "D:";
  1500.             break;
  1501.         case CMD_USE_B:
  1502.             fd_drive_id = "B:";
  1503.             menus[2].flags[1]    = 
  1504.             menus[2].flags[2]    =  ITEM_GREYED;
  1505.             break;
  1506.         case CMD_USE_RD:
  1507.             fd_drive_id  = "E:";
  1508.             menus[2].flags[1]    = 
  1509.             menus[2].flags[2]    =  ITEM_GREYED;
  1510.             break;
  1511.         case CMD_PAUSE_CSCAN:
  1512.         case CMD_PAUSE_SEEK:
  1513.         case CMD_PAUSE_READ:
  1514.         case CMD_PAUSE_WRITE:
  1515.         case CMD_PAUSE_ASCAN:
  1516.             if (!demo_control[(command & 0x0f)].suspended)
  1517.             {
  1518.                 menus[1].texts[(command & 0x0f)] = 
  1519.                     demo_control[(command & 0x0f)].resume_menu;
  1520.                 /* Hack. Change menu command from pause to resume */
  1521.                 menus[1].commands[(command & 0x0f)] -= 0x10;
  1522.                 menus[1].commands[(command & 0x0f)] |= 0x20;
  1523.  
  1524.                 /* Request it be suspended */
  1525.                 suspend_this_task =  demo_control[(command & 0x0f)].p_task;
  1526.                 /* And wait */
  1527.                 count(1, suspend_completed, SEC);
  1528.                 suspend_this_task =  (TCB_PTR) 0;
  1529.             }
  1530.             break;
  1531.         case CMD_RESUME_CSCAN:
  1532.         case CMD_RESUME_SEEK:
  1533.         case CMD_RESUME_READ:
  1534.         case CMD_RESUME_WRITE:
  1535.         case CMD_RESUME_ASCAN:
  1536.             if (demo_control[(command & 0x0f)].suspended)
  1537.             {
  1538.                 menus[1].texts[(command & 0x0f)] =
  1539.                      demo_control[(command & 0x0f)].pause_menu;
  1540.                 /* Hack. Change menu command from resume to pause */
  1541.                 menus[1].commands[(command & 0x0f)] -= 0x20;
  1542.                 menus[1].commands[(command & 0x0f)] |= 0x10;
  1543.                 demo_control[(command & 0x0f)].suspended = 0;
  1544.                 resume(demo_control[(command & 0x0f)].p_task);
  1545.             }
  1546.             break;
  1547.         default:
  1548.             break;
  1549.     }
  1550. }    
  1551.  
  1552. /* Other miscelanous control functions */
  1553.  
  1554. /* This is called from xmwin_epilogue in xmwin.c. The task must be locked on 
  1555.    entry.It suspends the current tasks and notes it in demo control structure 
  1556.    If requested it signals when the suspend is complete. This signaling
  1557.    mechanism is needed because opcon_main() asks the task to suspend and
  1558.    then waits for acknowledgement. This eliminates race conditions in the 
  1559.    menus.
  1560. */
  1561.  
  1562. void  fdemo_suspend_me(int do_signal)                             /* __fn__ */
  1563. {
  1564. int i;
  1565.     for (i = 0;i<MAXDEMOTASKS;i++)
  1566.     {
  1567.         if(demo_control[i].p_task == ct)
  1568.         {
  1569.             demo_control[i].suspended = 1;          /* yea */
  1570.             if (do_signal)
  1571.                 signal(suspend_completed);
  1572.             suspend(ct,INF);
  1573.             break;
  1574.         }
  1575.     }
  1576. }
  1577.  
  1578. /* Task error function. If called display the message in the tasks window
  1579.    and suspend forever */
  1580. void _cdecl xfd_error(char *p)                             /* __fn__ */
  1581. {
  1582. int i;
  1583. int j;
  1584. char display_buffer[70];
  1585.  
  1586.     for (i = 0; i < MAXDEMOTASKS; i++)
  1587.     {
  1588.         if (ct == demo_control[i].p_task)
  1589.         {
  1590.             /* Clear the window */
  1591.             memset(display_buffer,' ', 69);
  1592.             for (j = 1; j < demo_control[i].window->height-1; j++)
  1593.                 xmwin_wr_string(demo_control[i].window, 1, j, FGCOLOR, BGCOLOR, 
  1594.                                 display_buffer);
  1595.             xmwin_wr_string(demo_control[i].window, 1, 1, FGCOLOR, BGCOLOR, 
  1596.                             p);
  1597.             xmwin_wr_string(demo_control[i].window, 1, 2, FGCOLOR, BGCOLOR, 
  1598.                             "Bye.....");
  1599.             break;
  1600.         }
  1601.     }
  1602.     suspend(ct, INF);
  1603. }
  1604.  
  1605. /* These tasks don't do anything at the current time */
  1606. void _cdecl quit_appl()                                         /* __fn__ */
  1607. {
  1608. #if IDE_FLOPPY
  1609.     /* Restore interrupt vectors */
  1610.    fl_restore();
  1611. #endif
  1612.  
  1613.     /* Restore the screen */
  1614.     if (xfd_appl_win)
  1615.         xmwin_destroy(xfd_appl_win);
  1616.     clr_screen(LIGHTGRAY, BLACK);
  1617. }
  1618.  
  1619. void _cdecl show_etime()                                        /* __fn__ */
  1620. {
  1621.  
  1622. }
  1623.  
  1624.