Merge pull request #508 from wolfmanjm/fix/allow-space-in-filename-filter-panel-files
authorJim Morris <morris@wolfman.com>
Sat, 13 Sep 2014 08:15:40 +0000 (01:15 -0700)
committerJim Morris <morris@wolfman.com>
Sat, 13 Sep 2014 08:15:40 +0000 (01:15 -0700)
Fix/allow space in filename filter panel files

src/libs/utils.cpp
src/libs/utils.h
src/modules/utils/panel/screens/FileScreen.cpp
src/modules/utils/panel/screens/FileScreen.h
src/modules/utils/player/Player.cpp
src/modules/utils/player/Player.h

index 3395b54..097d522 100644 (file)
 #include "system_LPC17xx.h"
 #include "LPC17xx.h"
 #include "utils.h"
-using namespace std;
+
 #include <string>
-using std::string;
 #include <cstring>
 #include <stdio.h>
+using std::string;
 
 volatile bool _isr_context = false;
 
-uint16_t get_checksum(const string& to_check){
+uint16_t get_checksum(const string &to_check)
+{
     return get_checksum(to_check.c_str());
 }
 
-uint16_t get_checksum(const char* to_check){
-   // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum
-   uint16_t sum1 = 0;
-   uint16_t sum2 = 0;
-   const char* p= to_check;
-   char c;
-   while((c= *p++) != 0) {
-      sum1 = (sum1 + c) % 255;
-      sum2 = (sum2 + sum1) % 255;
-   }
-   return (sum2 << 8) | sum1;
+uint16_t get_checksum(const char *to_check)
+{
+    // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum
+    uint16_t sum1 = 0;
+    uint16_t sum2 = 0;
+    const char *p = to_check;
+    char c;
+    while((c = *p++) != 0) {
+        sum1 = (sum1 + c) % 255;
+        sum2 = (sum2 + sum1) % 255;
+    }
+    return (sum2 << 8) | sum1;
 }
 
-void get_checksums(uint16_t check_sums[], const string& key){
+void get_checksums(uint16_t check_sums[], const string &key)
+{
     check_sums[0] = 0x0000;
     check_sums[1] = 0x0000;
     check_sums[2] = 0x0000;
     size_t begin_key = 0;
     unsigned int counter = 0;
-    while( begin_key < key.size() && counter < 3 ){
+    while( begin_key < key.size() && counter < 3 ) {
         size_t end_key =  key.find_first_of(".", begin_key);
         string key_node;
         if(end_key == string::npos) {
-            key_node= key.substr(begin_key);
-        }else{
-            key_node= key.substr(begin_key, end_key-begin_key);
+            key_node = key.substr(begin_key);
+        } else {
+            key_node = key.substr(begin_key, end_key - begin_key);
         }
 
         check_sums[counter] = get_checksum(key_node);
@@ -91,52 +94,67 @@ bool is_whitespace(int c)
 }
 
 // Convert to lowercase
-string lc(string str){
-    for (unsigned int i=0; i<strlen(str.c_str()); i++)
-        if (str[i] >= 0x41 && str[i] <= 0x5A)
-        str[i] = str[i] + 0x20;
-    return str;
+string lc(const string &str)
+{
+    string lcstr;
+    for (auto c : str) {
+        lcstr.append(1, ::tolower(c));
+    }
+    return lcstr;
 }
 
 // Remove non-number characters
-string remove_non_number( string str ){
+string remove_non_number( string str )
+{
     string number_mask = "0123456789-.abcdefpxABCDEFPX";
-    size_t found=str.find_first_not_of(number_mask);
-    while (found!=string::npos){
+    size_t found = str.find_first_not_of(number_mask);
+    while (found != string::npos) {
         //str[found]='*';
-        str.replace(found,1,"");
-        found=str.find_first_not_of(number_mask);
+        str.replace(found, 1, "");
+        found = str.find_first_not_of(number_mask);
     }
     return str;
 }
 
 // Get the first parameter, and remove it from the original string
-string shift_parameter( string &parameters ){
+string shift_parameter( string &parameters )
+{
     size_t beginning = parameters.find_first_of(" ");
-    if( beginning == string::npos ){ string temp = parameters; parameters = ""; return temp; }
+    if( beginning == string::npos ) {
+        string temp = parameters;
+        parameters = "";
+        return temp;
+    }
     string temp = parameters.substr( 0, beginning );
-    parameters = parameters.substr(beginning+1, parameters.size());
+    parameters = parameters.substr(beginning + 1, parameters.size());
     return temp;
 }
 
 // Separate command from arguments
-string get_arguments( string possible_command ){
+string get_arguments( string possible_command )
+{
     size_t beginning = possible_command.find_first_of(" ");
-    if( beginning == string::npos ){ return ""; }
+    if( beginning == string::npos ) {
+        return "";
+    }
     return possible_command.substr( beginning + 1, possible_command.size() - beginning + 1);
 }
 
 // Returns true if the file exists
-bool file_exists( const string file_name ){
+bool file_exists( const string file_name )
+{
     bool exists = false;
     FILE *lp = fopen(file_name.c_str(), "r");
-    if(lp){ exists = true; }
+    if(lp) {
+        exists = true;
+    }
     fclose(lp);
     return exists;
 }
 
 // Prepares and executes a watchdog reset for dfu or reboot
-void system_reset( bool dfu ){
+void system_reset( bool dfu )
+{
     if(dfu) {
         LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
         uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
@@ -144,7 +162,7 @@ void system_reset( bool dfu ){
         LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
         LPC_WDT->WDFEED = 0xAA;                 // Kick the dog!
         LPC_WDT->WDFEED = 0x55;
-    }else{
+    } else {
         NVIC_SystemReset();
     }
 }
@@ -163,21 +181,21 @@ string absolute_from_relative( string path )
     }
 
     string match = "../" ;
-    while ( path.substr(0,3) == match ) {
+    while ( path.substr(0, 3) == match ) {
         path = path.substr(3);
         unsigned found = cwd.find_last_of("/");
-        cwd = cwd.substr(0,found);
+        cwd = cwd.substr(0, found);
     }
 
     match = ".." ;
-    if ( path.substr(0,2) == match ) {
+    if ( path.substr(0, 2) == match ) {
         path = path.substr(2);
         unsigned found = cwd.find_last_of("/");
-        cwd = cwd.substr(0,found);
+        cwd = cwd.substr(0, found);
     }
 
     if ( cwd[cwd.length() - 1] == '/' ) {
-         return cwd + path;
+        return cwd + path;
     }
 
     return cwd + '/' + path;
index 89169b9..a9ad3ff 100644 (file)
@@ -9,7 +9,7 @@ using std::string;
 
 extern volatile bool _isr_context;
 
-string lc(string str);
+string lc(const string& str);
 
 bool is_alpha( int );
 bool is_digit( int );
index 0d0b9f3..de02b8f 100644 (file)
@@ -36,7 +36,7 @@ void FileScreen::on_enter()
     if ( this->current_folder.compare("") == 0 ) {
         this->enter_folder("/");
     } else {
-        this->enter_folder(this->current_folder);
+        this->enter_folder(this->current_folder.c_str());
     }
 }
 
@@ -52,14 +52,13 @@ void FileScreen::on_refresh()
 }
 
 // Enter a new folder
-void FileScreen::enter_folder(std::string folder)
+void FileScreen::enter_folder(const char *folder)
 {
-
-    // Rembember where we are
+    // Remember where we are
     this->current_folder = folder;
 
     // We need the number of lines to setup the menu
-    uint16_t number_of_files_in_folder = this->count_folder_content(this->current_folder);
+    uint16_t number_of_files_in_folder = this->count_folder_content(this->current_folder.c_str());
 
     // Setup menu
     THEPANEL->setup_menu(number_of_files_in_folder + 1); // same number of files as menu items
@@ -92,18 +91,18 @@ void FileScreen::clicked_line(uint16_t line)
             if ( this->current_folder[this->current_folder.length() - 1] == '/' && this->current_folder.length() != 1 ) {
                 this->current_folder.erase(this->current_folder.length() - 1, 1);
             }
-            this->enter_folder(this->current_folder);
+            this->enter_folder(this->current_folder.c_str());
         }
     } else {
         //printf("enter file\r\n");
         // Enter file
         string path = this->current_folder;
-        if ( path.compare("/") == 0 ) {
+        if(path.compare("/") == 0) {
             path = "";
         }
         path = path + "/" + this->file_at( line - 1 );
-        if ( this->is_a_folder( path ) ) {
-            this->enter_folder(path);
+        if(this->is_a_folder(path.c_str())) {
+            this->enter_folder(path.c_str());
             return;
         }
 
@@ -115,15 +114,11 @@ void FileScreen::clicked_line(uint16_t line)
 }
 
 // Check wether a line is a folder or a file
-bool FileScreen::is_a_folder( string path )
+bool FileScreen::is_a_folder(const char *path)
 {
-    // In the special case of /local/ ( the mbed flash chip ) we don't have sub-folders, everything is a file
-    if ( path.substr(0, 7).compare("/local/") == 0 ) {
-        return false;
-    }
     // Else, check if it's a folder or not
     DIR *d;
-    d = opendir(path.c_str());
+    d = opendir(path);
     if (d == NULL) {
         return false;
     } else {
@@ -132,6 +127,16 @@ bool FileScreen::is_a_folder( string path )
     }
 }
 
+bool FileScreen::filter_file(const char *f)
+{
+    string fn= lc(f);
+    string path = this->current_folder;
+    if(path == "/") path= "";
+    path= path + "/" + fn;
+    // only filter files that have a .g in them and directories
+    return (is_a_folder(path.c_str()) || fn.find(".g") != string::npos);
+}
+
 // Find the "line"th file in the current folder
 string FileScreen::file_at(uint16_t line)
 {
@@ -141,14 +146,11 @@ string FileScreen::file_at(uint16_t line)
     d = opendir(this->current_folder.c_str());
     if (d != NULL) {
         while ((p = readdir(d)) != NULL) {
-            if ( count == line ) {
-                string to_return =  lc(string(p->d_name));
-                //printf("line: %u string:%s\r\n", line, to_return.c_str());
-                //if( to_return[to_return.length()-1] == '.' ){ to_return[to_return.length()-1] = 0x00; }
+            // only filter files that have a .g in them and directories
+            if(filter_file(p->d_name) && count++ == line ) {
                 closedir(d);
-                return to_return;
+                return p->d_name;
             }
-            count++;
         }
     }
 
@@ -156,23 +158,23 @@ string FileScreen::file_at(uint16_t line)
     return "";
 }
 
-// Count how many files there are in the current folder
-uint16_t FileScreen::count_folder_content(std::string folder)
+// Count how many files there are in the current folder that have a .g in them
+uint16_t FileScreen::count_folder_content(const char *folder)
 {
     DIR *d;
     struct dirent *p;
     uint16_t count = 0;
-    d = opendir(folder.c_str());
+    d = opendir(folder);
     if (d != NULL) {
         while ((p = readdir(d)) != NULL) {
-            count++;
+            if(filter_file(p->d_name)) count++;
         }
         closedir(d);
         return count;
-    } else {
-        return 0;
     }
+    return 0;
 }
+
 void FileScreen::on_main_loop()
 {
     if (this->start_play) {
@@ -187,7 +189,7 @@ void FileScreen::on_main_loop()
 void FileScreen::play(string path)
 {
     struct SerialMessage message;
-    message.message = string("play ") + path + " -q";
+    message.message = string("play ") + path;
     message.stream = &(StreamOutput::NullStream);
     THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message );
 }
index 7c4feaf..5ae8fd3 100644 (file)
@@ -19,19 +19,20 @@ class FileScreen : public PanelScreen {
         void on_enter();
         void on_refresh();
         void on_main_loop();
-        void enter_folder(std::string folder);
-        uint16_t count_folder_content(std::string folder);
         void clicked_line(uint16_t line);
         void display_menu_line(uint16_t line);
-        bool is_a_folder( string path );
-        string file_at(uint16_t line);
-
-        std::string current_folder;
 
     private:
+        void enter_folder(const char *folder);
+        bool is_a_folder(const char *path );
+        uint16_t count_folder_content(const char *folder);
+        string file_at(uint16_t line);
+        bool filter_file(const char *f);
         void play(string path);
-        bool start_play;
+
+        std::string current_folder;
         string play_path;
+        bool start_play;
 };
 
 
index 0db799e..6a1d38a 100644 (file)
@@ -54,6 +54,21 @@ void Player::on_second_tick(void *)
     if (!THEKERNEL->pauser->paused()) this->elapsed_secs++;
 }
 
+// extract any options found on line, terminates args at the space before the first option (-v)
+// eg this is a file.gcode -v
+//    will return -v and set args to this is a file.gcode
+string Player::extract_options(string& args)
+{
+    string opts;
+    size_t pos= args.find(" -");
+    if(pos != string::npos) {
+        opts= args.substr(pos);
+        args= args.substr(0, pos);
+    }
+
+    return opts;
+}
+
 void Player::on_gcode_received(void *argument)
 {
     Gcode *gcode = static_cast<Gcode *>(argument);
@@ -66,8 +81,7 @@ void Player::on_gcode_received(void *argument)
 
         } else if (gcode->m == 23) { // select file
             gcode->mark_as_taken();
-            // Get filename
-            this->filename = "/sd/" + shift_parameter( args );
+            this->filename = "/sd/" + args; // filename is whatever is in args
             this->current_stream = &(StreamOutput::NullStream);
 
             if(this->current_file_handler != NULL) {
@@ -144,7 +158,7 @@ void Player::on_gcode_received(void *argument)
         } else if (gcode->m == 32) { // select file and start print
             gcode->mark_as_taken();
             // Get filename
-            this->filename = "/sd/" + shift_parameter( args );
+            this->filename = "/sd/" + args; // filename is whatever is in args including spaces
             this->current_stream = &(StreamOutput::NullStream);
 
             if(this->current_file_handler != NULL) {
@@ -188,10 +202,10 @@ void Player::on_console_line_received( void *argument )
 // Play a gcode file by considering each line as if it was received on the serial console
 void Player::play_command( string parameters, StreamOutput *stream )
 {
-
-    // Get filename
-    this->filename          = absolute_from_relative(shift_parameter( parameters ));
-    string options          = shift_parameter( parameters );
+    // extract any options from the line and terminate the line there
+    string options= extract_options(parameters);
+    // Get filename which is the entire parameter line upto any options found or entire line
+    this->filename = absolute_from_relative(parameters);
 
     if(this->playing_file) {
         stream->printf("Currently printing, abort print first\r\n");
index c03269d..6bd0d56 100644 (file)
@@ -33,6 +33,7 @@ class Player : public Module {
         void play_command( string parameters, StreamOutput* stream );
         void progress_command( string parameters, StreamOutput* stream );
         void abort_command( string parameters, StreamOutput* stream );
+        string extract_options(string& args);
 
         string filename;