|
@@ -62,6 +62,7 @@ SdFile CardReader::root, CardReader::workDir, CardReader::workDirParents[MAX_DIR
|
62
|
62
|
uint8_t CardReader::workDirDepth;
|
63
|
63
|
|
64
|
64
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
|
65
|
+
|
65
|
66
|
uint16_t CardReader::sort_count;
|
66
|
67
|
#if ENABLED(SDSORT_GCODE)
|
67
|
68
|
bool CardReader::sort_alpha;
|
|
@@ -78,6 +79,7 @@ uint8_t CardReader::workDirDepth;
|
78
|
79
|
#if ENABLED(SDSORT_USES_RAM)
|
79
|
80
|
|
80
|
81
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
|
82
|
+ uint16_t CardReader::nrFiles; // Cached total file count
|
81
|
83
|
#if ENABLED(SDSORT_DYNAMIC_RAM)
|
82
|
84
|
char **CardReader::sortshort, **CardReader::sortnames;
|
83
|
85
|
#else
|
|
@@ -94,6 +96,7 @@ uint8_t CardReader::workDirDepth;
|
94
|
96
|
#elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
|
95
|
97
|
uint8_t CardReader::isDir[(SDSORT_LIMIT+7)>>3];
|
96
|
98
|
#endif
|
|
99
|
+ #define IS_DIR(n) TEST(isDir[(n) >> 3], (n) & 0x07)
|
97
|
100
|
#endif
|
98
|
101
|
|
99
|
102
|
#endif // SDSORT_USES_RAM
|
|
@@ -110,10 +113,6 @@ char CardReader::proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
110
|
113
|
|
111
|
114
|
uint32_t CardReader::filesize, CardReader::sdpos;
|
112
|
115
|
|
113
|
|
-LsAction CardReader::lsAction; //stored for recursion.
|
114
|
|
-uint16_t CardReader::nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
|
115
|
|
-char *CardReader::diveDirName;
|
116
|
|
-
|
117
|
116
|
CardReader::CardReader() {
|
118
|
117
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
119
|
118
|
sort_count = 0;
|
|
@@ -138,7 +137,10 @@ CardReader::CardReader() {
|
138
|
137
|
#endif
|
139
|
138
|
}
|
140
|
139
|
|
141
|
|
-char *createFilename(char *buffer, const dir_t &p) {
|
|
140
|
+//
|
|
141
|
+// Get a DOS 8.3 filename in its useful form
|
|
142
|
+//
|
|
143
|
+char *createFilename(char * const buffer, const dir_t &p) {
|
142
|
144
|
char *pos = buffer;
|
143
|
145
|
for (uint8_t i = 0; i < 11; i++) {
|
144
|
146
|
if (p.name[i] == ' ') continue;
|
|
@@ -149,24 +151,78 @@ char *createFilename(char *buffer, const dir_t &p) {
|
149
|
151
|
return buffer;
|
150
|
152
|
}
|
151
|
153
|
|
152
|
|
-/**
|
153
|
|
- * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
|
154
|
|
- * LS_Count - Add +1 to nrFiles for every file within the parent
|
155
|
|
- * LS_GetFilename - Get the filename of the file indexed by nrFile_index
|
156
|
|
- * LS_SerialPrint - Print the full path and size of each file to serial output
|
157
|
|
- */
|
|
154
|
+//
|
|
155
|
+// Return 'true' if the item is a folder or G-code file
|
|
156
|
+//
|
|
157
|
+bool CardReader::is_dir_or_gcode(const dir_t &p) {
|
|
158
|
+ uint8_t pn0 = p.name[0];
|
|
159
|
+
|
|
160
|
+ if ( pn0 == DIR_NAME_FREE || pn0 == DIR_NAME_DELETED // Clear or Deleted entry
|
|
161
|
+ || pn0 == '.' || longFilename[0] == '.' // Hidden file
|
|
162
|
+ || !DIR_IS_FILE_OR_SUBDIR(&p) // Not a File or Directory
|
|
163
|
+ || (p.attributes & DIR_ATT_HIDDEN) // Hidden by attribute
|
|
164
|
+ ) return false;
|
158
|
165
|
|
159
|
|
-uint16_t nrFile_index;
|
|
166
|
+ flag.filenameIsDir = DIR_IS_SUBDIR(&p); // We know it's a File or Folder
|
160
|
167
|
|
161
|
|
-void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=nullptr*/) {
|
|
168
|
+ return (
|
|
169
|
+ flag.filenameIsDir // All Directories are ok
|
|
170
|
+ || (p.name[8] == 'G' && p.name[9] != '~') // Non-backup *.G* files are accepted
|
|
171
|
+ );
|
|
172
|
+}
|
|
173
|
+
|
|
174
|
+//
|
|
175
|
+// Get the number of (compliant) items in the folder
|
|
176
|
+//
|
|
177
|
+int CardReader::countItems(SdFile dir) {
|
162
|
178
|
dir_t p;
|
163
|
|
- uint8_t cnt = 0;
|
|
179
|
+ int c = 0;
|
|
180
|
+ while (dir.readDir(&p, longFilename) > 0)
|
|
181
|
+ c += is_dir_or_gcode(p);
|
164
|
182
|
|
165
|
|
- // Read the next entry from a directory
|
166
|
|
- while (parent.readDir(&p, longFilename) > 0) {
|
|
183
|
+ #if ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES
|
|
184
|
+ nrFiles = c;
|
|
185
|
+ #endif
|
167
|
186
|
|
168
|
|
- // If the entry is a directory and the action is LS_SerialPrint
|
169
|
|
- if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
|
|
187
|
+ return c;
|
|
188
|
+}
|
|
189
|
+
|
|
190
|
+//
|
|
191
|
+// Get file/folder info for an item by index
|
|
192
|
+//
|
|
193
|
+void CardReader::selectByIndex(SdFile dir, const uint8_t index) {
|
|
194
|
+ dir_t p;
|
|
195
|
+ for (uint8_t cnt = 0; dir.readDir(&p, longFilename) > 0;) {
|
|
196
|
+ if (is_dir_or_gcode(p)) {
|
|
197
|
+ if (cnt == index) {
|
|
198
|
+ createFilename(filename, p);
|
|
199
|
+ return; // 0 based index
|
|
200
|
+ }
|
|
201
|
+ cnt++;
|
|
202
|
+ }
|
|
203
|
+ }
|
|
204
|
+}
|
|
205
|
+
|
|
206
|
+//
|
|
207
|
+// Get file/folder info for an item by name
|
|
208
|
+//
|
|
209
|
+void CardReader::selectByName(SdFile dir, const char * const match) {
|
|
210
|
+ dir_t p;
|
|
211
|
+ for (uint8_t cnt = 0; dir.readDir(&p, longFilename) > 0; cnt++) {
|
|
212
|
+ if (is_dir_or_gcode(p)) {
|
|
213
|
+ createFilename(filename, p);
|
|
214
|
+ if (strcasecmp(match, filename) == 0) return;
|
|
215
|
+ }
|
|
216
|
+ }
|
|
217
|
+}
|
|
218
|
+
|
|
219
|
+//
|
|
220
|
+// Recursive method to list all files within a folder
|
|
221
|
+//
|
|
222
|
+void CardReader::printListing(SdFile parent, const char * const prepend/*=nullptr*/) {
|
|
223
|
+ dir_t p;
|
|
224
|
+ while (parent.readDir(&p, longFilename) > 0) {
|
|
225
|
+ if (DIR_IS_SUBDIR(&p)) {
|
170
|
226
|
|
171
|
227
|
// Get the short name for the item, which we know is a folder
|
172
|
228
|
char dosFilename[FILENAME_LENGTH];
|
|
@@ -188,68 +244,38 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
188
|
244
|
|
189
|
245
|
// Get a new directory object using the full path
|
190
|
246
|
// and dive recursively into it.
|
191
|
|
- SdFile dir;
|
192
|
|
- if (!dir.open(&parent, dosFilename, O_READ)) {
|
193
|
|
- if (lsAction == LS_SerialPrint) {
|
194
|
|
- SERIAL_ECHO_START();
|
195
|
|
- SERIAL_ECHOLNPAIR(MSG_SD_CANT_OPEN_SUBDIR, dosFilename);
|
196
|
|
- }
|
|
247
|
+ SdFile child;
|
|
248
|
+ if (!child.open(&parent, dosFilename, O_READ)) {
|
|
249
|
+ SERIAL_ECHO_START();
|
|
250
|
+ SERIAL_ECHOLNPAIR(MSG_SD_CANT_OPEN_SUBDIR, dosFilename);
|
197
|
251
|
}
|
198
|
|
- lsDive(path, dir);
|
|
252
|
+ printListing(child, path);
|
199
|
253
|
// close() is done automatically by destructor of SdFile
|
200
|
254
|
}
|
201
|
|
- else {
|
202
|
|
- uint8_t pn0 = p.name[0];
|
203
|
|
- if (pn0 == DIR_NAME_FREE) break;
|
204
|
|
- if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
|
205
|
|
- if (longFilename[0] == '.') continue;
|
206
|
|
-
|
207
|
|
- if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
|
208
|
|
-
|
209
|
|
- flag.filenameIsDir = DIR_IS_SUBDIR(&p);
|
210
|
|
-
|
211
|
|
- if (!flag.filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
|
212
|
|
-
|
213
|
|
- switch (lsAction) { // 1 based file count
|
214
|
|
- case LS_Count:
|
215
|
|
- nrFiles++;
|
216
|
|
- break;
|
217
|
|
-
|
218
|
|
- case LS_SerialPrint:
|
219
|
|
- createFilename(filename, p);
|
220
|
|
- if (prepend) SERIAL_ECHO(prepend);
|
221
|
|
- SERIAL_ECHO(filename);
|
222
|
|
- SERIAL_CHAR(' ');
|
223
|
|
- SERIAL_ECHOLN(p.fileSize);
|
224
|
|
- break;
|
225
|
|
-
|
226
|
|
- case LS_GetFilename:
|
227
|
|
- createFilename(filename, p);
|
228
|
|
- if (match != nullptr) {
|
229
|
|
- if (strcasecmp(match, filename) == 0) return;
|
230
|
|
- }
|
231
|
|
- else if (cnt == nrFile_index) return; // 0 based index
|
232
|
|
- cnt++;
|
233
|
|
- break;
|
234
|
|
- }
|
235
|
|
-
|
|
255
|
+ else if (is_dir_or_gcode(p)) {
|
|
256
|
+ createFilename(filename, p);
|
|
257
|
+ if (prepend) SERIAL_ECHO(prepend);
|
|
258
|
+ SERIAL_ECHO(filename);
|
|
259
|
+ SERIAL_CHAR(' ');
|
|
260
|
+ SERIAL_ECHOLN(p.fileSize);
|
236
|
261
|
}
|
237
|
|
- } // while readDir
|
|
262
|
+ }
|
238
|
263
|
}
|
239
|
264
|
|
|
265
|
+//
|
|
266
|
+// List all files on the SD card
|
|
267
|
+//
|
240
|
268
|
void CardReader::ls() {
|
241
|
|
- lsAction = LS_SerialPrint;
|
242
|
269
|
root.rewind();
|
243
|
|
- lsDive(nullptr, root);
|
|
270
|
+ printListing(root);
|
244
|
271
|
}
|
245
|
272
|
|
246
|
273
|
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
247
|
274
|
|
248
|
|
- /**
|
249
|
|
- * Get a long pretty path based on a DOS 8.3 path
|
250
|
|
- */
|
251
|
|
- void CardReader::printLongPath(char *path) {
|
252
|
|
- lsAction = LS_GetFilename;
|
|
275
|
+ //
|
|
276
|
+ // Get a long pretty path based on a DOS 8.3 path
|
|
277
|
+ //
|
|
278
|
+ void CardReader::printLongPath(char * const path) {
|
253
|
279
|
|
254
|
280
|
int i, pathLen = strlen(path);
|
255
|
281
|
|
|
@@ -275,7 +301,7 @@ void CardReader::ls() {
|
275
|
301
|
|
276
|
302
|
// Find the item, setting the long filename
|
277
|
303
|
diveDir.rewind();
|
278
|
|
- lsDive(nullptr, diveDir, segment);
|
|
304
|
+ selectByName(diveDir, segment);
|
279
|
305
|
|
280
|
306
|
// Print /LongNamePart to serial output
|
281
|
307
|
SERIAL_CHAR('/');
|
|
@@ -305,16 +331,16 @@ void CardReader::ls() {
|
305
|
331
|
|
306
|
332
|
#endif // LONG_FILENAME_HOST_SUPPORT
|
307
|
333
|
|
308
|
|
-/**
|
309
|
|
- * Echo the DOS 8.3 filename (and long filename, if any)
|
310
|
|
- */
|
|
334
|
+//
|
|
335
|
+// Echo the DOS 8.3 filename (and long filename, if any)
|
|
336
|
+//
|
311
|
337
|
void CardReader::printFilename() {
|
312
|
338
|
if (file.isOpen()) {
|
313
|
339
|
char dosFilename[FILENAME_LENGTH];
|
314
|
340
|
file.getDosName(dosFilename);
|
315
|
341
|
SERIAL_ECHO(dosFilename);
|
316
|
342
|
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
317
|
|
- getfilename(0, dosFilename);
|
|
343
|
+ selectFileByName(dosFilename);
|
318
|
344
|
if (longFilename[0]) {
|
319
|
345
|
SERIAL_ECHO(' ');
|
320
|
346
|
SERIAL_ECHO(longFilename);
|
|
@@ -339,10 +365,7 @@ void CardReader::mount() {
|
339
|
365
|
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
340
|
366
|
&& !sd2card.init(SPI_SPEED, LCD_SDSS)
|
341
|
367
|
#endif
|
342
|
|
- ) {
|
343
|
|
- //if (!sd2card.init(SPI_HALF_SPEED,SDSS))
|
344
|
|
- SERIAL_ECHO_MSG(MSG_SD_INIT_FAIL);
|
345
|
|
- }
|
|
368
|
+ ) SERIAL_ECHO_MSG(MSG_SD_INIT_FAIL);
|
346
|
369
|
else if (!volume.init(&sd2card))
|
347
|
370
|
SERIAL_ERROR_MSG(MSG_SD_VOL_INIT_FAIL);
|
348
|
371
|
else if (!root.openRoot(&volume))
|
|
@@ -354,7 +377,7 @@ void CardReader::mount() {
|
354
|
377
|
settings.first_load();
|
355
|
378
|
#endif
|
356
|
379
|
}
|
357
|
|
- setroot();
|
|
380
|
+ cdroot();
|
358
|
381
|
|
359
|
382
|
ui.refresh();
|
360
|
383
|
}
|
|
@@ -401,26 +424,32 @@ void CardReader::openLogFile(char * const path) {
|
401
|
424
|
openFile(path, false);
|
402
|
425
|
}
|
403
|
426
|
|
404
|
|
-void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
|
405
|
|
- file.getDosName(dst);
|
406
|
|
- while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
|
407
|
|
- if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
|
408
|
|
-}
|
409
|
|
-
|
410
|
|
-void CardReader::getAbsFilename(char *t) {
|
411
|
|
- *t++ = '/'; // Root folder
|
|
427
|
+//
|
|
428
|
+// Get the root-relative DOS path of the selected file
|
|
429
|
+//
|
|
430
|
+void CardReader::getAbsFilename(char *dst) {
|
|
431
|
+ *dst++ = '/';
|
412
|
432
|
uint8_t cnt = 1;
|
413
|
433
|
|
414
|
|
- for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir
|
415
|
|
- appendAtom(workDirParents[i], t, cnt);
|
|
434
|
+ auto appendAtom = [&](SdFile &file) {
|
|
435
|
+ file.getDosName(dst);
|
|
436
|
+ while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
|
|
437
|
+ if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
|
|
438
|
+ };
|
|
439
|
+
|
|
440
|
+ for (uint8_t i = 0; i < workDirDepth; i++) // Loop down to current work dir
|
|
441
|
+ appendAtom(workDirParents[i]);
|
416
|
442
|
|
417
|
443
|
if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH) - 1) { // Leave room for filename and nul
|
418
|
|
- appendAtom(file, t, cnt);
|
419
|
|
- --t;
|
|
444
|
+ appendAtom(file);
|
|
445
|
+ --dst;
|
420
|
446
|
}
|
421
|
|
- *t = '\0';
|
|
447
|
+ *dst = '\0';
|
422
|
448
|
}
|
423
|
449
|
|
|
450
|
+//
|
|
451
|
+// Open a file by DOS path - for read or write
|
|
452
|
+//
|
424
|
453
|
void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
|
425
|
454
|
|
426
|
455
|
if (!isMounted()) return;
|
|
@@ -472,7 +501,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
472
|
501
|
SERIAL_ECHOLNPAIR(MSG_SD_FILE_OPENED, fname, MSG_SD_SIZE, filesize);
|
473
|
502
|
SERIAL_ECHOLNPGM(MSG_SD_FILE_SELECTED);
|
474
|
503
|
|
475
|
|
- getfilename(0, fname);
|
|
504
|
+ selectFileByName(fname);
|
476
|
505
|
ui.set_status(longFilename[0] ? longFilename : fname);
|
477
|
506
|
//if (longFilename[0]) {
|
478
|
507
|
// SERIAL_ECHOPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
|
|
@@ -486,7 +515,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
486
|
515
|
SERIAL_ECHOLNPAIR(MSG_SD_OPEN_FILE_FAIL, fname, ".");
|
487
|
516
|
else {
|
488
|
517
|
flag.saving = true;
|
489
|
|
- getfilename(0, fname);
|
|
518
|
+ selectFileByName(fname);
|
490
|
519
|
#if ENABLED(EMERGENCY_PARSER)
|
491
|
520
|
emergency_parser.disable();
|
492
|
521
|
#endif
|
|
@@ -496,6 +525,9 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
496
|
525
|
}
|
497
|
526
|
}
|
498
|
527
|
|
|
528
|
+//
|
|
529
|
+// Delete a file by name in the working directory
|
|
530
|
+//
|
499
|
531
|
void CardReader::removeFile(const char * const name) {
|
500
|
532
|
if (!isMounted()) return;
|
501
|
533
|
|
|
@@ -527,7 +559,7 @@ void CardReader::report_status() {
|
527
|
559
|
SERIAL_ECHOLNPGM(MSG_SD_NOT_PRINTING);
|
528
|
560
|
}
|
529
|
561
|
|
530
|
|
-void CardReader::write_command(char *buf) {
|
|
562
|
+void CardReader::write_command(char * const buf) {
|
531
|
563
|
char* begin = buf;
|
532
|
564
|
char* npos = nullptr;
|
533
|
565
|
char* end = buf + strlen(buf) - 1;
|
|
@@ -584,7 +616,7 @@ void CardReader::checkautostart() {
|
584
|
616
|
|
585
|
617
|
void CardReader::beginautostart() {
|
586
|
618
|
autostart_index = 0;
|
587
|
|
- setroot();
|
|
619
|
+ cdroot();
|
588
|
620
|
}
|
589
|
621
|
|
590
|
622
|
void CardReader::closefile(const bool store_location) {
|
|
@@ -602,38 +634,42 @@ void CardReader::closefile(const bool store_location) {
|
602
|
634
|
}
|
603
|
635
|
}
|
604
|
636
|
|
605
|
|
-/**
|
606
|
|
- * Get the name of a file in the current directory by index
|
607
|
|
- * with optional name to match.
|
608
|
|
- */
|
609
|
|
-void CardReader::getfilename(uint16_t nr, const char * const match/*=nullptr*/) {
|
|
637
|
+//
|
|
638
|
+// Get info for a file in the working directory by index
|
|
639
|
+//
|
|
640
|
+void CardReader::selectFileByIndex(const uint16_t nr) {
|
610
|
641
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
611
|
|
- if (match != nullptr) {
|
612
|
|
- while (nr < sort_count) {
|
613
|
|
- if (strcasecmp(match, sortshort[nr]) == 0) break;
|
614
|
|
- nr++;
|
615
|
|
- }
|
616
|
|
- }
|
617
|
642
|
if (nr < sort_count) {
|
618
|
643
|
strcpy(filename, sortshort[nr]);
|
619
|
644
|
strcpy(longFilename, sortnames[nr]);
|
620
|
|
- flag.filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
|
|
645
|
+ flag.filenameIsDir = IS_DIR(nr);
|
621
|
646
|
return;
|
622
|
647
|
}
|
623
|
|
- #endif // SDSORT_CACHE_NAMES
|
624
|
|
- lsAction = LS_GetFilename;
|
625
|
|
- nrFile_index = nr;
|
|
648
|
+ #endif
|
|
649
|
+ workDir.rewind();
|
|
650
|
+ selectByIndex(workDir, nr);
|
|
651
|
+}
|
|
652
|
+
|
|
653
|
+//
|
|
654
|
+// Get info for a file in the working directory by DOS name
|
|
655
|
+//
|
|
656
|
+void CardReader::selectFileByName(const char * const match) {
|
|
657
|
+ #if ENABLED(SDSORT_CACHE_NAMES)
|
|
658
|
+ for (int nr = 0; nr < sort_count; nr++)
|
|
659
|
+ if (strcasecmp(match, sortshort[nr]) == 0) {
|
|
660
|
+ strcpy(filename, sortshort[nr]);
|
|
661
|
+ strcpy(longFilename, sortnames[nr]);
|
|
662
|
+ flag.filenameIsDir = IS_DIR(nr);
|
|
663
|
+ return;
|
|
664
|
+ }
|
|
665
|
+ #endif
|
626
|
666
|
workDir.rewind();
|
627
|
|
- lsDive(nullptr, workDir, match);
|
|
667
|
+ selectByName(workDir, match);
|
628
|
668
|
}
|
629
|
669
|
|
630
|
670
|
uint16_t CardReader::countFilesInWorkDir() {
|
631
|
|
- lsAction = LS_Count;
|
632
|
|
- nrFiles = 0;
|
633
|
671
|
workDir.rewind();
|
634
|
|
- lsDive(nullptr, workDir);
|
635
|
|
- //SERIAL_ECHOLN(nrFiles);
|
636
|
|
- return nrFiles;
|
|
672
|
+ return countItems(workDir);
|
637
|
673
|
}
|
638
|
674
|
|
639
|
675
|
/**
|
|
@@ -650,11 +686,11 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
650
|
686
|
static SdFile newDir1, newDir2;
|
651
|
687
|
SdFile *sub = &newDir1, *startDir;
|
652
|
688
|
|
653
|
|
- const char *dirname_start = path;
|
|
689
|
+ const char *item_name_adr = path;
|
654
|
690
|
if (path[0] == '/') {
|
655
|
691
|
curDir = &root;
|
656
|
692
|
workDirDepth = 0;
|
657
|
|
- dirname_start++;
|
|
693
|
+ item_name_adr++;
|
658
|
694
|
}
|
659
|
695
|
else
|
660
|
696
|
curDir = &workDir;
|
|
@@ -662,15 +698,15 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
662
|
698
|
startDir = curDir;
|
663
|
699
|
|
664
|
700
|
// Start dive
|
665
|
|
- while (dirname_start) {
|
|
701
|
+ while (item_name_adr) {
|
666
|
702
|
// Find next sub
|
667
|
|
- char * const dirname_end = strchr(dirname_start, '/');
|
668
|
|
- if (dirname_end <= dirname_start) break;
|
|
703
|
+ char * const name_end = strchr(item_name_adr, '/');
|
|
704
|
+ if (name_end <= item_name_adr) break;
|
669
|
705
|
|
670
|
706
|
// Set subDirName
|
671
|
|
- const uint8_t len = dirname_end - dirname_start;
|
|
707
|
+ const uint8_t len = name_end - item_name_adr;
|
672
|
708
|
char dosSubdirname[len + 1];
|
673
|
|
- strncpy(dosSubdirname, dirname_start, len);
|
|
709
|
+ strncpy(dosSubdirname, item_name_adr, len);
|
674
|
710
|
dosSubdirname[len] = 0;
|
675
|
711
|
|
676
|
712
|
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
|
@@ -693,13 +729,13 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
693
|
729
|
// Point sub pointer to unused newDir
|
694
|
730
|
sub = (curDir != &newDir1) ? &newDir1 : &newDir2;
|
695
|
731
|
|
696
|
|
- // dirname_start point to next sub
|
697
|
|
- dirname_start = dirname_end + 1;
|
|
732
|
+ // item_name_adr point to next sub
|
|
733
|
+ item_name_adr = name_end + 1;
|
698
|
734
|
}
|
699
|
|
- return dirname_start;
|
|
735
|
+ return item_name_adr;
|
700
|
736
|
}
|
701
|
737
|
|
702
|
|
-void CardReader::chdir(const char * relpath) {
|
|
738
|
+void CardReader::cd(const char * relpath) {
|
703
|
739
|
SdFile newDir;
|
704
|
740
|
SdFile *parent = workDir.isOpen() ? &workDir : &root;
|
705
|
741
|
|
|
@@ -718,7 +754,7 @@ void CardReader::chdir(const char * relpath) {
|
718
|
754
|
}
|
719
|
755
|
}
|
720
|
756
|
|
721
|
|
-int8_t CardReader::updir() {
|
|
757
|
+int8_t CardReader::cdup() {
|
722
|
758
|
if (workDirDepth > 0) { // At least 1 dir has been saved
|
723
|
759
|
workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
|
724
|
760
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
|
@@ -729,7 +765,7 @@ int8_t CardReader::updir() {
|
729
|
765
|
return workDirDepth;
|
730
|
766
|
}
|
731
|
767
|
|
732
|
|
-void CardReader::setroot() {
|
|
768
|
+void CardReader::cdroot() {
|
733
|
769
|
workDir = root;
|
734
|
770
|
flag.workDirIsRoot = true;
|
735
|
771
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
|
@@ -740,10 +776,10 @@ void CardReader::setroot() {
|
740
|
776
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
741
|
777
|
|
742
|
778
|
/**
|
743
|
|
- * Get the name of a file in the current directory by sort-index
|
|
779
|
+ * Get the name of a file in the working directory by sort-index
|
744
|
780
|
*/
|
745
|
781
|
void CardReader::getfilename_sorted(const uint16_t nr) {
|
746
|
|
- getfilename(
|
|
782
|
+ selectFileByIndex(
|
747
|
783
|
#if ENABLED(SDSORT_GCODE)
|
748
|
784
|
sort_alpha &&
|
749
|
785
|
#endif
|
|
@@ -757,7 +793,7 @@ void CardReader::setroot() {
|
757
|
793
|
#define SET_SORTNAME(I) (sortnames[I] = strdup(longest_filename()))
|
758
|
794
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
759
|
795
|
// When caching also store the short name, since
|
760
|
|
- // we're replacing the getfilename() behavior.
|
|
796
|
+ // we're replacing the selectFileByIndex() behavior.
|
761
|
797
|
#define SET_SORTSHORT(I) (sortshort[I] = strdup(filename))
|
762
|
798
|
#else
|
763
|
799
|
#define SET_SORTSHORT(I) NOOP
|
|
@@ -854,7 +890,7 @@ void CardReader::setroot() {
|
854
|
890
|
i);
|
855
|
891
|
// If using RAM then read all filenames now.
|
856
|
892
|
#if ENABLED(SDSORT_USES_RAM)
|
857
|
|
- getfilename(i);
|
|
893
|
+ selectFileByIndex(i);
|
858
|
894
|
SET_SORTNAME(i);
|
859
|
895
|
SET_SORTSHORT(i);
|
860
|
896
|
// char out[30];
|
|
@@ -871,8 +907,17 @@ void CardReader::setroot() {
|
871
|
907
|
// Bubble Sort
|
872
|
908
|
for (uint16_t i = fileCnt; --i;) {
|
873
|
909
|
bool didSwap = false;
|
|
910
|
+ uint8_t o1 = sort_order[0];
|
|
911
|
+ #if DISABLED(SDSORT_USES_RAM)
|
|
912
|
+ selectFileByIndex(o1); // Pre-fetch the first entry and save it
|
|
913
|
+ strcpy(name1, longest_filename()); // so the loop only needs one fetch
|
|
914
|
+ #if HAS_FOLDER_SORTING
|
|
915
|
+ bool dir1 = flag.filenameIsDir;
|
|
916
|
+ #endif
|
|
917
|
+ #endif
|
|
918
|
+
|
874
|
919
|
for (uint16_t j = 0; j < i; ++j) {
|
875
|
|
- const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
|
|
920
|
+ const uint16_t o2 = sort_order[j + 1];
|
876
|
921
|
|
877
|
922
|
// Compare names from the array or just the two buffered names
|
878
|
923
|
#if ENABLED(SDSORT_USES_RAM)
|
|
@@ -884,12 +929,7 @@ void CardReader::setroot() {
|
884
|
929
|
#if HAS_FOLDER_SORTING
|
885
|
930
|
#if ENABLED(SDSORT_USES_RAM)
|
886
|
931
|
// Folder sorting needs an index and bit to test for folder-ness.
|
887
|
|
- const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
|
888
|
|
- ind2 = o2 >> 3, bit2 = o2 & 0x07;
|
889
|
|
- #define _SORT_CMP_DIR(fs) \
|
890
|
|
- (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
|
891
|
|
- ? _SORT_CMP_NODIR() \
|
892
|
|
- : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
|
|
932
|
+ #define _SORT_CMP_DIR(fs) IS_DIR(o1) == IS_DIR(o2) ? _SORT_CMP_NODIR() : IS_DIR(fs > 0 ? o1 : o2)
|
893
|
933
|
#else
|
894
|
934
|
#define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
|
895
|
935
|
#endif
|
|
@@ -898,13 +938,9 @@ void CardReader::setroot() {
|
898
|
938
|
// The most economical method reads names as-needed
|
899
|
939
|
// throughout the loop. Slow if there are many.
|
900
|
940
|
#if DISABLED(SDSORT_USES_RAM)
|
901
|
|
- getfilename(o1);
|
902
|
|
- strcpy(name1, longest_filename()); // save (or getfilename below will trounce it)
|
903
|
|
- #if HAS_FOLDER_SORTING
|
904
|
|
- bool dir1 = flag.filenameIsDir;
|
905
|
|
- #endif
|
906
|
|
- getfilename(o2);
|
907
|
|
- char *name2 = longest_filename(); // use the string in-place
|
|
941
|
+ selectFileByIndex(o2);
|
|
942
|
+ const bool dir2 = flag.filenameIsDir;
|
|
943
|
+ char * const name2 = longest_filename(); // use the string in-place
|
908
|
944
|
#endif // !SDSORT_USES_RAM
|
909
|
945
|
|
910
|
946
|
// Sort the current pair according to settings.
|
|
@@ -919,10 +955,22 @@ void CardReader::setroot() {
|
919
|
955
|
_SORT_CMP_NODIR()
|
920
|
956
|
#endif
|
921
|
957
|
) {
|
|
958
|
+ // Reorder the index, indicate that sorting happened
|
|
959
|
+ // Note that the next o1 will be the current o1. No new fetch needed.
|
922
|
960
|
sort_order[j] = o2;
|
923
|
961
|
sort_order[j + 1] = o1;
|
924
|
962
|
didSwap = true;
|
925
|
963
|
}
|
|
964
|
+ else {
|
|
965
|
+ // The next o1 is the current o2. No new fetch needed.
|
|
966
|
+ o1 = o2;
|
|
967
|
+ #if DISABLED(SDSORT_USES_RAM)
|
|
968
|
+ #if HAS_FOLDER_SORTING
|
|
969
|
+ dir1 = dir2;
|
|
970
|
+ #endif
|
|
971
|
+ strcpy(name1, name2);
|
|
972
|
+ #endif
|
|
973
|
+ }
|
926
|
974
|
}
|
927
|
975
|
if (!didSwap) break;
|
928
|
976
|
}
|
|
@@ -944,10 +992,10 @@ void CardReader::setroot() {
|
944
|
992
|
sortshort = new char*[1];
|
945
|
993
|
isDir = new uint8_t[1];
|
946
|
994
|
#endif
|
947
|
|
- getfilename(0);
|
|
995
|
+ selectFileByIndex(0);
|
948
|
996
|
SET_SORTNAME(0);
|
949
|
997
|
SET_SORTSHORT(0);
|
950
|
|
- isDir[0] = flag.filenameIsDir ? 0x01 : 0x00;
|
|
998
|
+ isDir[0] = flag.filenameIsDir;
|
951
|
999
|
#endif
|
952
|
1000
|
}
|
953
|
1001
|
|
|
@@ -984,6 +1032,9 @@ uint16_t CardReader::get_num_Files() {
|
984
|
1032
|
;
|
985
|
1033
|
}
|
986
|
1034
|
|
|
1035
|
+//
|
|
1036
|
+// Return from procedure or close out the Print Job
|
|
1037
|
+//
|
987
|
1038
|
void CardReader::printingHasFinished() {
|
988
|
1039
|
planner.synchronize();
|
989
|
1040
|
file.close();
|