I was unsatisfied with KermM's C port of AHelper's C++ file browser library. It caused a lot of system errors on my under-development image viewer, and its code "complexity" annoyed me as a beginner in C coding.
So I wrote my own file browser, first for specific purposes and now modified to fit most usage cases. It doesn't use dynamic memory allocation and supports a maximum of 200 files or folders per directory (same as OS).
Long file names are supported (that and the fact that it doesn't show the filesize are probably the reasons why it doesn't mimic the OS so well).
I'm yet to get a single system error with it.

I believe the code is pretty self-explanatory and easy to change according to your needs. There's an usage example at the bottom (and after removing it, the code should compile as-is).
When compiling, one or two warnings are returned but I don't know how to fix them.
Tell me if something doesn't work.


Code:
/* FILE BROWSER "LIBRARY" for the Casio Prizm series of calculators
   Version 1.0 - Dec. 20, 2012
   For use along with libfxcg.
   Written by: gbl08ma <gbl08ma@gmail.com> - http://gbl08ma.com
               at tny. internet media - http://i.tny.im
   Released as public domain code
   (but giving credit where possible won't hurt anyone, even though
   it isn't a must).
   
   This code is designed to mimic as much as possible the default
   OS file selecting screens like those seen in Picture Plot and
   eActivity.
*/
void CopySpriteMasked(const unsigned char* data, int x, int y, int width, int height, int maskcolor) {
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(LCD_WIDTH_PX*y + x);
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
         if ((((((int)(*data))&0x000000FF)<<8) | ((((int)(*(data+1))))&0x000000FF)) != maskcolor) {
            *(VRAM++) = *(data++);
            *(VRAM++) = *(data++);
         } else { VRAM += 2; data += 2; }
      }
      VRAM += 2*(LCD_WIDTH_PX-width);
   }
}
const color_t folder_icon[510] = {
      0xf81f,0xf81f,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,
      0xf81f,0x52aa,0xdef9,0xfffc,0xfffc,0xffba,0xde74,0x52aa,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,
      0x52aa,0xdef9,0xfffc,0xffbc,0xffba,0xffb9,0xff78,0xde74,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xf81f,
      0x52aa,0xfffc,0xffbb,0xffba,0xffb9,0xff78,0xff76,0xff34,0xff34,0xfef3,0xf6f1,0xf6f1,0xf6f1,0xf6f1,0xf6f1,0x52aa,0xf81f,
      0x52aa,0xffbb,0xffbb,0xffb9,0xff78,0xff76,0xff74,0xff34,0xfef3,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xffbb,0xffb9,0xff77,0xff76,0xff35,0xff34,0xfef2,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6b1,0xf6f1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xffb9,0xff78,0xff76,0xff35,0xff34,0xfef2,0xf6f2,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff77,0xff76,0xff35,0xff33,0xff33,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xeef1,0xf6b1,0xf6b1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff76,0xff75,0xff34,0xfef3,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xff35,0xff33,0xff32,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff33,0xff33,0xf6b2,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xfef3,0xf6f1,0xf6b1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0x52aa,0xad55,
      0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xad55,
      0xf81f,0xf81f,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55
   };
typedef struct
{
  char filename[256]; //filename, not proper for use with Bfile.
  char name[120]; //friendly name (without //fls0/ or complete path)
  int isfolder;
} File;
typedef struct
{
   unsigned short id, type;
   unsigned long fsize, dsize;
   unsigned int property;
   unsigned long address;
} file_type_t;
int GetFiles(File files[], char* basepath, unsigned char* filter) {
  /*searches storage memory for folders and filtered files, returns their count*/
  /*basepath should start with \\fls0\ and should always have a slash (\) at the end */
   unsigned short path[0x10A], found[0x10A];
   unsigned char buffer[0x10A];

   // make the buffer
   strcpy((char*)buffer, basepath);
   strcat((char*)buffer, "*");
   
   int curitem = 0;
   file_type_t fileinfo;
   int findhandle;
   Bfile_StrToName_ncpy(path, buffer, 0x10A);
   int ret = Bfile_FindFirst_NON_SMEM((const char*)path, &findhandle, (char*)found, &fileinfo);
   Bfile_StrToName_ncpy(path, filter, 0x10A);
   while(!ret) {
      Bfile_NameToStr_ncpy(buffer, found, 0x10A);
      if(!(strcmp((char*)buffer, "..") == 0 || strcmp((char*)buffer, ".") == 0 || strcmp((char*)buffer, "@MainMem") == 0) &&
         (fileinfo.fsize == 0 || Bfile_Name_MatchMask((const short int*)path, (const short int*)found)))
      {
         strcpy(files[curitem].name, (char*)buffer);
         strcpy(files[curitem].filename, basepath);
         strcat(files[curitem].filename, (char*)buffer);
         if(fileinfo.fsize == 0) files[curitem].isfolder = 1; else files[curitem].isfolder = 0;
         curitem++;
      }
      ret = Bfile_FindNext_NON_SMEM(findhandle, (char*)found, (char*)&fileinfo);
   }
   Bfile_FindClose(findhandle);
   
   return curitem;
}

char browserbasepath[256] = "\\\\fls0\\"; //this has to be out of fileBrowser, if you want to return to the last browsed folder when calling fileBrowser again.
void fileBrowser(char* filename, unsigned char* filter, char* title) {
  int inloop = 1;
  //<--- put browserbasepath in this line if you don't want it to persist between fileBrowser calls
  int curSelFile = 1;
  while(inloop) {
    int key, inscreen = 1, scroll=0, numfiles=0;
    curSelFile = 1;
    File files[200];
   
    Bdisp_AllClr_VRAM();
    DisplayStatusArea();
    numfiles = GetFiles(files, browserbasepath, filter);
    while(inscreen) {
      Bdisp_AllClr_VRAM();
      int curfile = 0; //current processing file
      if (numfiles>0) {
        while(curfile < numfiles) {
          unsigned char menuitem[100] = "";
          strcpy((char*)menuitem, "  ");
          strcat((char*)menuitem, "  "); //add space for an icon
          strcat((char*)menuitem, (char*)files[curfile].name);
          strcat((char*)menuitem, "                     "); //make sure we have a string big enough to have background when item is selected
          if(scroll < curfile+1) {
            PrintXY(1,curfile+2-scroll,(char*)menuitem, (curSelFile == curfile+1 ? TEXT_MODE_INVERT : TEXT_MODE_TRANSPARENT_BACKGROUND), TEXT_COLOR_BLACK);     
            if (files[curfile].isfolder == 1) {
              if((curfile+2-scroll)>=2&&(curfile+2-scroll)<=7) CopySpriteMasked((unsigned char*)folder_icon, 18, (curfile+2-scroll)*24+4, 17, 15, 0xf81f  );
            }
          }
          curfile++;
        }
        //hide 8th item
        PrintXY(1,8,(char*)"                        ", TEXT_MODE_NORMAL, TEXT_COLOR_BLACK);
 
        TScrollbar sb;
        sb.I1 = 0;
        sb.I5 = 0;
        sb.indicatormaximum = numfiles;
        sb.indicatorheight = 6;
        sb.indicatorpos = scroll;
        sb.barheight = LCD_HEIGHT_PX - 24*3;
        sb.bartop = 24;
        sb.barleft = LCD_WIDTH_PX - 6;
        sb.barwidth = 6;
        Scrollbar(&sb);
      } else {
        PrintXY(8,4,(char*)"  No Data", TEXT_MODE_TRANSPARENT_BACKGROUND, TEXT_COLOR_BLACK);
      }
      DisplayStatusArea();
      char titleBuffer[23] = "";
      strcpy(titleBuffer, "  ");
      strcat(titleBuffer, title);
      PrintXY(1, 1, titleBuffer, TEXT_MODE_TRANSPARENT_BACKGROUND, TEXT_COLOR_BLUE);
      int textX=strlen(title)*18+10, textY=6;
      char friendlypath[256] = "";
      strcpy(friendlypath, browserbasepath+6);
      friendlypath[strlen(friendlypath)-1] = '\0'; //remove ending slash like OS does
      PrintMini(&textX, &textY, (unsigned char*)friendlypath, 0, 0xFFFFFFFF, 0, 0, COLOR_BLACK, COLOR_WHITE, 1, 0);
      int iresult;
      if(numfiles>0) {
        GetFKeyPtr(0x03B1, &iresult); // OPEN
        FKey_Display(0, (int*)iresult);
      }
      GetKey(&key);
      switch(key)
      {
        case KEY_CTRL_DOWN:
          if(curSelFile == numfiles)
          {
            curSelFile = 1;
            scroll = 0;
          }
          else
          {
            curSelFile++;
            if(curSelFile > scroll+(numfiles>6 ? 6 : numfiles))
              scroll = curSelFile -(numfiles>6 ? 6 : numfiles);
          }
          break;
        case KEY_CTRL_UP:
          if(curSelFile == 1)
          {
            curSelFile = numfiles;
            scroll = curSelFile-(numfiles>6 ? 6 : numfiles);
          }
          else
          {
            curSelFile--;
            if(curSelFile-1 < scroll)
              scroll = curSelFile -1;
          }
          break;
        case KEY_CTRL_EXE:
        case KEY_CTRL_F1:
          if(files[curSelFile-1].isfolder) {
            strcpy(browserbasepath, files[curSelFile-1].filename); //switch to selected folder
            strcat(browserbasepath, "\\");
            inscreen = 0; //reload at new folder
          } else {
            strcpy(filename, files[curSelFile-1].filename);
            return;
          }
          break;
        case KEY_CTRL_EXIT:
           if(!strcmp(browserbasepath,"\\\\fls0\\")) { //check that we aren't already in the root folder
             //we are, return
            return;
          } else {
             int i=strlen(browserbasepath)-2;
             while (i>=0 && browserbasepath[i] != '\\')
                i--;
             if (browserbasepath[i] == '\\') {
              char tmp[256] = "";
              memcpy(tmp,browserbasepath,i+1);
              tmp[i+1] = '\0';
              strcpy(browserbasepath, tmp);
             }
            inscreen = 0; //reload at new folder
          }
          break;
      }
    }
  }
}

/*  USAGE EXAMPLE:  */
char filename[256] = "";
fileBrowser(filename, (unsigned char*)"*.txt", "Title"); //*.txt: filetype to filter; "Title": small text to show in blue on the top left corner
if(!strcmp(filename, "")) {
   //user didn't select a file (pressed EXIT at root folder)
} else {
   //user selected a file
   //do something with filename (which isn't proper for use with Bfile functions, you need to use Bfile_StrToName_ncpy first!
}
How much static stack space does it take up, if it doesn't do any dynamic allocation? I agree that my code is "complex", but only in that I needed to emulate class instance variable storage by passing around structs, and the automatic constructors and destructors that C++ creates for allocating and deallocating instance variables with functions. I'm sad to hear that you found it glitchy.
It uses at least 75991 bytes of stack space while the execution is inside the fileBrowser routine, and that is assuming the values for buffers from the code above. There's 512 KB stack so this shouldn't be a problem unless one has many static buffers declared and code in memory when fileBrowser is called.
alloca() alloca() alloca(). That's quickly becoming my mantra when people complain about the heap being nasty to work with.
Oh, alloca is like malloc but for the stack, and is automatically freed? I have to try that.

I don't use the heap on the Prizm because the OS doesn't seem to like it very much, furthermore, it's small (128kB) when compared to the stack (512kB).
Will you be releasing the "general" version of your file browser, or is this about it? Mind if I give it a try in LuaZM, slash is it appropriate for that?

Edit: What would be the easiest way to make this allow more than one extension, say, *.txt|*.lua? or even *.txt|*.lua|*.lc?
This is the general version of the file browser Smile
I believe it is appropriate for use in LuaZM. As said, it uses a quite a large fixed amount of memory (I figured out using alloca for variably sized allocations would require me to get the number of items in a directory first, allocate space, and only then list the items, which would decrease the speed), but that memory is "freed" when you're not using the file browser, so just make sure to free all Lua-related resources when using the file browser (something I bet you already do) so there's always enough RAM.

Also, it still doesn't have checks to see if a directory has more than 200 items (which is the OS limit), meaning that if one does there will be an array overflow. I added this check in the snippet below, near line 85.

Currently the file browser only allows to filter for one file type, but you can make it filter more than one file type at once by adding more filter buffers, converting them to shorts with the syscall and then adding another if clause for them.

I did the work for you (but didn't compile it, and any errors it may have should be trivial to fix):

Code:

/* FILE BROWSER "LIBRARY" for the Casio Prizm series of calculators
   Version 1.0a - Dec. 24, 2012
   For use along with libfxcg. Filters for three file types and checks for
   too many items in a directory to prevent overflows.
   Written by: gbl08ma <gbl08ma@gmail.com> - http://gbl08ma.com
               at tny. internet media - http://i.tny.im
   Released as public domain code
   (but giving credit where possible won't hurt anyone, even though
   it isn't a must).
   
   This code is designed to mimic as much as possible the default
   OS file selecting screens like those seen in Picture Plot and
   eActivity.
*/
void CopySpriteMasked(const unsigned char* data, int x, int y, int width, int height, int maskcolor) { 
   char* VRAM = (char*)0xA8000000; 
   VRAM += 2*(LCD_WIDTH_PX*y + x); 
   for(int j=y; j<y+height; j++) { 
      for(int i=x; i<x+width;  i++) { 
         if ((((((int)(*data))&0x000000FF)<<8) | ((((int)(*(data+1))))&0x000000FF)) != maskcolor) { 
            *(VRAM++) = *(data++); 
            *(VRAM++) = *(data++); 
         } else { VRAM += 2; data += 2; } 
      } 
      VRAM += 2*(LCD_WIDTH_PX-width); 
   } 
}
const color_t folder_icon[510] = {
      0xf81f,0xf81f,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,
      0xf81f,0x52aa,0xdef9,0xfffc,0xfffc,0xffba,0xde74,0x52aa,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,0xf81f,
      0x52aa,0xdef9,0xfffc,0xffbc,0xffba,0xffb9,0xff78,0xde74,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xf81f,
      0x52aa,0xfffc,0xffbb,0xffba,0xffb9,0xff78,0xff76,0xff34,0xff34,0xfef3,0xf6f1,0xf6f1,0xf6f1,0xf6f1,0xf6f1,0x52aa,0xf81f,
      0x52aa,0xffbb,0xffbb,0xffb9,0xff78,0xff76,0xff74,0xff34,0xfef3,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xffbb,0xffb9,0xff77,0xff76,0xff35,0xff34,0xfef2,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6b1,0xf6f1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xffb9,0xff78,0xff76,0xff35,0xff34,0xfef2,0xf6f2,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff77,0xff76,0xff35,0xff33,0xff33,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xeef1,0xf6b1,0xf6b1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff76,0xff75,0xff34,0xfef3,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xff35,0xff33,0xff32,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xff33,0xff33,0xf6b2,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0x52aa,0xad55,
      0x52aa,0xfef3,0xf6f1,0xf6b1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0x52aa,0xad55,
      0x52aa,0xf6f1,0xf6b1,0xf6f1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xf6b1,0xf6f1,0xeeb1,0xf6f1,0x52aa,0xad55,
      0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0x52aa,0xad55,
      0xf81f,0xf81f,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55,0xad55
   };
typedef struct
{
  char filename[256]; //filename, not proper for use with Bfile.
  char name[120]; //friendly name (without //fls0/ or complete path)
  int isfolder;
} File;
typedef struct
{
   unsigned short id, type;
   unsigned long fsize, dsize;
   unsigned int property;
   unsigned long address;
} file_type_t;
#define MAX_ITEMS_IN_DIR 200
int GetFiles(File files[], char* basepath, unsigned char* filter, unsigned char* filter2, unsigned char* filter3) {
  /*searches storage memory for folders and filtered files, returns their count*/
  /*basepath should start with \\fls0\ and should always have a slash (\) at the end */
   unsigned short path[0x10A], path2[0x10A], path3[0x10A], found[0x10A];
   unsigned char buffer[0x10A];

   // make the buffer
   strcpy((char*)buffer, basepath);
   strcat((char*)buffer, "*");
   
   int curitem = 0;
   file_type_t fileinfo;
   int findhandle;
   Bfile_StrToName_ncpy(path, buffer, 0x10A);
   int ret = Bfile_FindFirst_NON_SMEM((const char*)path, &findhandle, (char*)found, &fileinfo);
   Bfile_StrToName_ncpy(path, filter, 0x10A);
   Bfile_StrToName_ncpy(path2, filter2, 0x10A);
   Bfile_StrToName_ncpy(path3, filter3, 0x10A);
   while(!ret) {
      Bfile_NameToStr_ncpy(buffer, found, 0x10A);
      if(!(strcmp((char*)buffer, "..") == 0 || strcmp((char*)buffer, ".") == 0 || strcmp((char*)buffer, "@MainMem") == 0) &&
         (fileinfo.fsize == 0 || Bfile_Name_MatchMask((const short int*)path, (const short int*)found)  || Bfile_Name_MatchMask((const short int*)path2, (const short int*)found)  || Bfile_Name_MatchMask((const short int*)path3, (const short int*)found)))
      {
         strcpy(files[curitem].name, (char*)buffer);
         strcpy(files[curitem].filename, basepath);
         strcat(files[curitem].filename, (char*)buffer);
         if(fileinfo.fsize == 0) files[curitem].isfolder = 1; else files[curitem].isfolder = 0;
         curitem++;
      }
      if (curitem>MAX_ITEMS_IN_DIR) {
        // A message box could go here telling the user that there are more than 200 files and so some will be skipped (this is what the OS does).
        break; // Don't find more files, the array is full.
      }
      ret = Bfile_FindNext_NON_SMEM(findhandle, (char*)found, (char*)&fileinfo);
   }
   Bfile_FindClose(findhandle);
   
   return curitem;
}

char browserbasepath[256] = "\\\\fls0\\"; //this has to be out of fileBrowser, if you want to return to the last browsed folder when calling fileBrowser again.
void fileBrowser(char* filename, unsigned char* filter, unsigned char* filter2, unsigned char* filter3, char* title) {
  int inloop = 1;
  //<--- put browserbasepath in this line if you don't want it to persist between fileBrowser calls
  int curSelFile = 1;
  while(inloop) {
    int key, inscreen = 1, scroll=0, numfiles=0;
    curSelFile = 1;
    File files[MAX_ITEMS_IN_DIR]; 
     
    Bdisp_AllClr_VRAM();
    DisplayStatusArea();
    numfiles = GetFiles(files, browserbasepath, filter, filter2, filter3);
    while(inscreen) {
      Bdisp_AllClr_VRAM();
      int curfile = 0; //current processing file
      if (numfiles>0) {
        while(curfile < numfiles) {
          unsigned char menuitem[100] = "";
          strcpy((char*)menuitem, "  ");
          strcat((char*)menuitem, "  "); //add space for an icon
          strcat((char*)menuitem, (char*)files[curfile].name);
          strcat((char*)menuitem, "                     "); //make sure we have a string big enough to have background when item is selected
          if(scroll < curfile+1) {
            PrintXY(1,curfile+2-scroll,(char*)menuitem, (curSelFile == curfile+1 ? TEXT_MODE_INVERT : TEXT_MODE_TRANSPARENT_BACKGROUND), TEXT_COLOR_BLACK);     
            if (files[curfile].isfolder == 1) {
              if((curfile+2-scroll)>=2&&(curfile+2-scroll)<=7) CopySpriteMasked((unsigned char*)folder_icon, 18, (curfile+2-scroll)*24+4, 17, 15, 0xf81f  );
            }
          }
          curfile++;
        }
        //hide 8th item
        PrintXY(1,8,(char*)"                        ", TEXT_MODE_NORMAL, TEXT_COLOR_BLACK);
   
        TScrollbar sb;
        sb.I1 = 0;
        sb.I5 = 0;
        sb.indicatormaximum = numfiles;
        sb.indicatorheight = 6;
        sb.indicatorpos = scroll;
        sb.barheight = LCD_HEIGHT_PX - 24*3;
        sb.bartop = 24;
        sb.barleft = LCD_WIDTH_PX - 6;
        sb.barwidth = 6;
        Scrollbar(&sb);
      } else {
        PrintXY(8,4,(char*)"  No Data", TEXT_MODE_TRANSPARENT_BACKGROUND, TEXT_COLOR_BLACK);
      }
      DisplayStatusArea();
      char titleBuffer[23] = "";
      strcpy(titleBuffer, "  ");
      strcat(titleBuffer, title);
      PrintXY(1, 1, titleBuffer, TEXT_MODE_TRANSPARENT_BACKGROUND, TEXT_COLOR_BLUE);
      int textX=strlen(title)*18+10, textY=6;
      char friendlypath[256] = "";
      strcpy(friendlypath, browserbasepath+6);
      friendlypath[strlen(friendlypath)-1] = '\0'; //remove ending slash like OS does
      PrintMini(&textX, &textY, (unsigned char*)friendlypath, 0, 0xFFFFFFFF, 0, 0, COLOR_BLACK, COLOR_WHITE, 1, 0);
      int iresult;
      if(numfiles>0) {
        GetFKeyPtr(0x03B1, &iresult); // OPEN
        FKey_Display(0, (int*)iresult);
      }
      GetKey(&key);
      switch(key)
      {
        case KEY_CTRL_DOWN:
          if(curSelFile == numfiles)
          {
            curSelFile = 1;
            scroll = 0;
          }
          else
          {
            curSelFile++;
            if(curSelFile > scroll+(numfiles>6 ? 6 : numfiles))
              scroll = curSelFile -(numfiles>6 ? 6 : numfiles);
          }
          break;
        case KEY_CTRL_UP:
          if(curSelFile == 1)
          {
            curSelFile = numfiles;
            scroll = curSelFile-(numfiles>6 ? 6 : numfiles);
          }
          else
          {
            curSelFile--;
            if(curSelFile-1 < scroll)
              scroll = curSelFile -1;
          }
          break;
        case KEY_CTRL_EXE:
        case KEY_CTRL_F1:
          if(files[curSelFile-1].isfolder) {
            strcpy(browserbasepath, files[curSelFile-1].filename); //switch to selected folder
            strcat(browserbasepath, "\\");
            inscreen = 0; //reload at new folder
          } else {
            strcpy(filename, files[curSelFile-1].filename);
            return;
          }
          break;
        case KEY_CTRL_EXIT:
           if(!strcmp(browserbasepath,"\\\\fls0\\")) { //check that we aren't already in the root folder
             //we are, return
            return;
          } else {
             int i=strlen(browserbasepath)-2;
             while (i>=0 && browserbasepath[i] != '\\')
                i--;
             if (browserbasepath[i] == '\\') {
              char tmp[256] = "";
              memcpy(tmp,browserbasepath,i+1);
              tmp[i+1] = '\0';
              strcpy(browserbasepath, tmp);
             }
            inscreen = 0; //reload at new folder
          }
          break;
      }
    }
  }
}

/*  USAGE EXAMPLE:  */
char filename[256] = "";
fileBrowser(filename, (unsigned char*)"*.lua", (unsigned char*)"*.lc", (unsigned char*)"*.txt", "Title"); //*.lua, *.lc, *.txt: filetypes to filter; "Title": small text to show in blue on the top left corner
if(!strcmp(filename, "")) {
   //user didn't select a file (pressed EXIT at root folder)
} else {
   //user selected a file
   //do something with filename (which isn't proper for use with Bfile functions, you need to use Bfile_StrToName_ncpy first!
}


Also, feel free to adjust the size for the name buffers so that they can hold longer filenames and paths (and for the sake of it, also add a check to see if a path is going to fit in them, etc.; now I understand why Casio limits the end-user to see 8-chars filenames...)
Thanks a lot for helping me with those edits; my fingers aren't quite up to it, nor is my brain pre-coffee. Smile I need to finish my zmg_drawcirclefilled routine before I can compile, then I shall test and let you know if it works.
I'm trying the one in the first post, but I keep getting this error:

Code:
../..//include/fxcg\display.h:81:3: error: expected identifier before numeric co
nstant
../..//include/fxcg\display.h:93:3: error: expected identifier before numeric co
nstant
TextInput.c: In function 'fileBrowser':
TextInput.c:645:9: error: unknown type name 'scrollbar'
TextInput.c:646:11: error: request for member 'I1' in something not a structure
or union
TextInput.c:647:11: error: request for member 'I5' in something not a structure
or union
TextInput.c:648:11: error: request for member 'indicatormaximum' in something no
t a structure or union
TextInput.c:649:11: error: request for member 'indicatorheight' in something not
 a structure or union
TextInput.c:650:11: error: request for member 'indicatorpos' in something not a
structure or union
TextInput.c:651:11: error: request for member 'barheight' in something not a str
ucture or union
TextInput.c:652:11: error: request for member 'bartop' in something not a struct
ure or union
TextInput.c:653:11: error: request for member 'barleft' in something not a struc
ture or union
TextInput.c:654:11: error: request for member 'barwidth' in something not a stru
cture or union
TextInput.c:655:9: warning: passing argument 1 of 'Scrollbar' from incompatible
pointer type [enabled by default]
../..//include/fxcg\display.h:123:6: note: expected 'struct scrollbar *' but arg
ument is of type 'int *'
TextInput.c: In function 'main':
TextInput.c:760:23: error: 'hFile' undeclared (first use in this function)
TextInput.c:760:23: note: each undeclared identifier is reported only once for e
ach function it appears in
TextInput.c:778:5: warning: implicit declaration of function 'Bdisp_AllCr_VRAM'
[-Wimplicit-function-declaration]
make: *** [TextInput.o] Error 1


I'm using the latest version of libfxcg.

Edit: Nevermind. I got that error out of the way. Now I'm getting:

Code:
TextInput.o: In function `_GetFiles':
TextInput.c:(.text+0x115c): undefined reference to `_Bfile_Name_MatchMask'
TextInput.o: In function `_fileBrowser':
TextInput.c:(.text+0x1338): undefined reference to `_Bfile_Name_MatchMask'
collect2: ld returned 1 exit status
make: *** [Input.bin] Error 1
That's not a fault in my code. You should be using the latest version of libfxcg (as in: compile it yourself from the code in GitHub).
Or grab an automated build.
I have a question about this. The filename it returns, does it include the "\\\\fls0\"? or do I have to add that when I do the StrToName_ncpy?
It includes the \\fls0\ portion. You only need to do the StrToName_ncpy to use it with the Bfile functions.
The filename it gives back is something like "\\\fls0\[filename]". It should be "\\\\fls0\\[filename]". Is there any way I can modify it to make it work?
Spenceboy98 wrote:
The filename it gives back is something like "\\\fls0\[filename]". It should be "\\\\fls0\\[filename]". Is there any way I can modify it to make it work?

It is working as it should. The "\" is an escape sequence ("" is the escape character) which makes a single backslash "". When you put the string "\\\\fls0\" in your C program, the C compiler recognizes that you are escaping the "" and knows what you mean, "\\fls0".
But Bfile_StrToName_ncpy doesn't work with it. Sad
What do you mean by "doesn't work with"?
Well, I'm guessing that it isn't working with StrToName_ncpy, or OpenFile. The hFile it gives back is less than 0, so it is returning without examining the file like I need it to. This is the parts of my code:


Code:
    unsigned short buffer[sizeof(PATH)*2];
    Bfile_StrToName_ncpy(buffer, (unsigned char*)PATH, sizeof(PATH));
    int hFile = Bfile_OpenFile_OS(buffer, 3);
    if(hFile < 0){
        PrintMiniFix(40, 200, PATH, 0x40, COLOR_RED, COLOR_DARKGRAY);


It's in a function, so the PATH is the filename returned from your routine.
Try putting strlen(PATH)+1 instead of sizeof(PATH) on the second line of the snippet you posted.
I think you're mixing sizeof and strlen a bit. sizeof is the fixed data size (be it an int, a short, a char, etc.) and strlen is for measuring the length of char arrays (strings). Google it. You cannot use strlen when declaring arrays like array[size of array] because the size of arrays isn't dynamic in C, so the way you're using sizeof in the first line seems correct to me.
gbl08ma wrote:
Try putting strlen(PATH)+1 instead of sizeof(PATH) on the second line of the snippet you posted.
I think you're mixing sizeof and strlen a bit. sizeof is the fixed data size (be it an int, a short, a char, etc.) and strlen is for measuring the length of char arrays (strings). Google it. You cannot use strlen when declaring arrays like array[size of array] because the size of arrays isn't dynamic in C, so the way you're using sizeof in the first line seems correct to me.


Thanks. It works now. The tutorial on WikiPrizm says sizeof(), so I just used that.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement