home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsm / randjpeg / source / c / randfile < prev    next >
Encoding:
Text File  |  1995-12-27  |  3.4 KB  |  142 lines

  1. /* randfile.c
  2.  * MACHINE:     RISC OS 3.60
  3.  * LANGUAGE:    Acorn C v5.06
  4.  * LIBRARIES:   OSLib
  5.  * AUTHOR:      Cy Booker <cy@cheepnis.demon.co.uk>
  6.  * LICENCE:     Freeware, copyright 1995
  7.  */
  8.  
  9. #include "randfile.h"
  10.  
  11.  
  12. #include <assert.h>
  13. #include <stddef.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17.  
  18. #include "OS:osgbpb.h"
  19. #include "OS:macros.h"
  20.  
  21.  
  22. #include "main.h"
  23. #include "strings.h"
  24.  
  25.  
  26.  
  27. /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  28.  */
  29.  
  30. static void scan_files(
  31.                 strings         *s,
  32.                 const char      *path);
  33.  
  34.  
  35.  
  36. /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  37.  */
  38.  
  39. extern char *rand_file(
  40.                 const char      *path,
  41.                 const char      *history_file) {
  42.   static const strings  empty = {NULL, NULL, 0};
  43.   strings       history = empty;
  44.   strings       todo = empty;
  45.   strings       done = empty;
  46.   node          *node;
  47.   char          *file;
  48.  
  49.   assert(path);
  50.   strings_read(&history, history_file);
  51.   scan_files(&todo, path);
  52.   if (todo.count == 0) {
  53.     strings_clear(&done);
  54.     strings_clear(&todo);
  55.     return NULL;
  56.   }
  57.  
  58.   while (todo.count > 0) {
  59.     node = strings_get(&todo, rand() % todo.count);
  60.     if (strings_find(&history, node->text) == NULL) {
  61.       /*
  62.        * add this node to the history
  63.        */
  64.       strings_remove(&todo, node);
  65.       goto done;
  66.     }
  67.     strings_remove(&todo, node);
  68.     strings_insert(&done, node);
  69.   }
  70.   /*
  71.    * ok, special case, we've done all of them!
  72.    */
  73.   strings_clear(&history);
  74.   node = strings_get(&done, rand() % done.count);
  75.   assert(node);
  76.   strings_remove(&done, node);
  77. done:
  78.   assert(node);
  79.   strings_insert(&history, node);
  80.   strings_clear(&done);
  81.   strings_clear(&todo);
  82.   file = xmalloc(strlen(node->text) + 1);
  83.   strcpy(file, node->text);
  84.   strings_write(&history, history_file);
  85.   strings_clear(&history);
  86.   return file;
  87. }
  88.  
  89.  
  90.  
  91. /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  92.  * for now path must be a directory name without the '.'
  93.  */
  94.  
  95. static void scan_files(
  96.                 strings         *s,
  97.                 const char      *path) {
  98.   int                           context = 0;
  99.   int                           count;
  100.   char                          buffer[512];            /* nice and big */
  101.   const osgbpb_info_stamped     *info;
  102.   char                          *obj;
  103.  
  104.   assert(s);
  105.   assert(path);
  106.  
  107.   do {
  108.     context = osgbpb_dir_entries_info_stamped(
  109.                 path,
  110.                 (osgbpb_info_stamped_list *)buffer,
  111.                 sizeof(buffer) / sizeof(osgbpb_info_stamped),
  112.                 context,
  113.                 sizeof(buffer),
  114.                 NULL,                   /* all entries */
  115.                 &count);
  116.     info = (const osgbpb_info_stamped *)buffer;
  117.     for (; (count > 0); count--) {
  118.       obj = xmalloc(strlen(path) + 1 + strlen(info->name) + 1);
  119.       strcat(strcat(strcpy(obj, path), "."), info->name);
  120.       switch (info->obj_type) {
  121.       case fileswitch_IS_DIR:
  122.       case fileswitch_IS_IMAGE:
  123.         scan_files(s, obj);
  124.         break;
  125.  
  126.       case fileswitch_IS_FILE:
  127.         if (info->file_type == 0xc85) {
  128.           strings_add(s, obj);
  129.         }
  130.         break;
  131.       }
  132.       free(obj);
  133.       info = (const osgbpb_info_stamped *)
  134.                 (((const char *)info)
  135.                         + offsetof(osgbpb_info_stamped, name)
  136.                         + ALIGN(strlen(info->name) + 1));
  137.     }
  138.   } while (context != -1);
  139. }
  140.  
  141.  
  142.