1321 lines
32 KiB
C
1321 lines
32 KiB
C
/***********************************************************************
|
|
*
|
|
* Copyright (c) 2006 Palm, Inc. or its subsidiaries.
|
|
* All rights reserved.
|
|
*
|
|
***********************************************************************/
|
|
|
|
/** @ingroup MiniImage
|
|
*
|
|
**/
|
|
|
|
/** @file FileBrowserForm.c
|
|
* This file contains file browser functions for MiniImage
|
|
**/
|
|
|
|
/** @name
|
|
*
|
|
**/
|
|
/*@{*/
|
|
|
|
/***********************************************************************
|
|
*
|
|
* File:
|
|
* FileBrowserForm.c
|
|
*
|
|
* Description:
|
|
* File browsing form
|
|
*
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include <PalmOS.h>
|
|
#include <VfsMgr.h>
|
|
#include <DataMgr.h>
|
|
#include <PalmUtils.h>
|
|
#include <HsNav.h>
|
|
#include <HsKeyCommon.h>
|
|
|
|
#include "Common.h"
|
|
#include "FileBrowserForm.h"
|
|
#include "FileBrowserFormRsrc.h"
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Internal Defines
|
|
*
|
|
***********************************************************************/
|
|
|
|
#define dataBaseType 'temp'
|
|
#define dbCardNumber 0
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Internal typedef
|
|
*
|
|
***********************************************************************/
|
|
|
|
typedef struct
|
|
{
|
|
Boolean selected;
|
|
UInt16 attribute;
|
|
UInt32 fileSize;
|
|
Char* fileName;
|
|
|
|
} FileBrowserFileInfo;
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Internal functions
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Err PrvFormInit(FormType* frmP);
|
|
static void PrvFormDeInit();
|
|
|
|
Err PrvEnumerate();
|
|
static Err PrvEmptyDB();
|
|
static Err PrvAddRecord(FileInfoType* fileInfoP, UInt32 fileSize);
|
|
static Err PrvGetRecord(UInt16 index, FileBrowserFileInfo* fileInfoP, MemHandle* hP);
|
|
static void PrvReleaseRecord(UInt16 index, MemHandle h);
|
|
static void PrvDBSort();
|
|
|
|
static void PrvListViewInit(FormType* frmP);
|
|
static void PrvListViewDrawFile(void* tableP, Int16 row, Int16 column, RectangleType* boundsP);
|
|
static void PrvListViewLoadTable(FormType* frmP, Boolean redraw);
|
|
static void PrvDrawTableBorder(FormType* frmP);
|
|
static void PrvSelectFile(UInt16 index);
|
|
void FileBrowserTestScrolling(TablePtr tableP);
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Internal Globals
|
|
*
|
|
***********************************************************************/
|
|
|
|
static DmOpenRef gDB = NULL; // Global pointer to the database
|
|
static UInt16 gRowCount = 0; // Number of row in table/list view
|
|
static UInt16 gTopIndex = 0; // Top index item of the table
|
|
static UInt32 gFileCount = 0; // Number of files in database
|
|
static UInt16 gVolumeCount = 0; // Number of cards
|
|
static UInt16 gCurrentVolume = 0;
|
|
static Char gCurrentPath[MAX_PATH_LENGTH] = { NULL };
|
|
static Char gCurrentFile[MAX_FILENAME_LENGTH] = { NULL };
|
|
|
|
static WinHandle gDocumentWinH = 0; // Document Bitmap buffer
|
|
static WinHandle gFolderWinH = 0; // Folder Bitmap buffer
|
|
static UInt32 gReturnForm = 0; // Form to return to
|
|
static FileBrowserCallback gCallback = NULL; // Callback
|
|
|
|
//static FileBrowserView gViewType = DIRECTORY | FILE; // Show files and folders
|
|
//static FileBrowserSelection gSelectionType = SINGLE; // Single selection
|
|
|
|
Int8 selectedRow;
|
|
|
|
//flag to keep track of when scrolling has been used
|
|
Boolean gScrolling = false;
|
|
//flag to keep track of when the 5-way has been used
|
|
//this flag is true when 5-way is used but need not be set to false
|
|
Boolean gUsedUpDown = false;
|
|
|
|
#pragma mark ---------- File Browser Functions ----------
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserFormHandleEvent
|
|
*
|
|
* DESCRIPTION: This routine handles the events for the File Browser Form
|
|
*
|
|
* PARAMETERS: eventP - The pointer to the event.
|
|
*
|
|
* RETURNED: True if handled.
|
|
*
|
|
***********************************************************************/
|
|
|
|
Boolean FileBrowserFormHandleEvent(EventType * eventP)
|
|
{
|
|
TablePtr tableP;
|
|
Boolean handled = false;
|
|
FormType * frmP = FrmGetActiveForm();
|
|
|
|
switch (eventP->eType)
|
|
{
|
|
|
|
case keyDownEvent:
|
|
|
|
switch( eventP->data.keyDown.chr)
|
|
{
|
|
case vchrRockerUp:
|
|
case vchrPageUp:
|
|
{
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
|
|
/* to get 5-way to sync with scrolling */
|
|
FileBrowserTestScrolling(tableP);
|
|
|
|
//after we sync 5-way with scrolling, we can set the flag to false
|
|
gScrolling = false;
|
|
|
|
|
|
// Check that the selected row is within bounds and adjust focus to the selected row
|
|
|
|
// Table is highlighted, we're not at the top of list
|
|
if( selectedRow != -1 && selectedRow != 0) {
|
|
// Scroll up
|
|
if(selectedRow == gTopIndex) {
|
|
gTopIndex--;
|
|
selectedRow--;
|
|
PrvListViewLoadTable(frmP, true);
|
|
TblUnhighlightSelection(tableP);
|
|
TblRedrawTable(tableP);
|
|
} else { // No scrolling
|
|
selectedRow--;
|
|
}
|
|
TblSelectItem (tableP, selectedRow - gTopIndex, 0);
|
|
}
|
|
|
|
// set flag to show that 5-way has been used
|
|
gUsedUpDown = true;
|
|
|
|
handled = true;
|
|
break;
|
|
}
|
|
|
|
case vchrRockerDown:
|
|
case vchrPageDown:
|
|
{
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
|
|
/* to get 5-way to sync with scrolling */
|
|
FileBrowserTestScrolling(tableP);
|
|
|
|
//after we sync 5-way with scrolling, we can set the flag to false
|
|
gScrolling = false;
|
|
|
|
|
|
// Check that the selected row is within bounds and adjust focus to the selected row
|
|
|
|
// Table is highlighted and we're not at the bottom of list
|
|
if(selectedRow != -1 && selectedRow != (gFileCount - 1)) {
|
|
|
|
if(selectedRow < (gTopIndex + gRowCount - 1)) { // No scrolling
|
|
selectedRow++;
|
|
TblSelectItem (tableP, selectedRow - gTopIndex, 0);
|
|
|
|
} else { // Scroll
|
|
|
|
gTopIndex++;
|
|
selectedRow++;
|
|
TblUnhighlightSelection(tableP);
|
|
TblRedrawTable(tableP);
|
|
PrvListViewLoadTable(frmP, true);
|
|
TblSelectItem (tableP, selectedRow - gTopIndex, 0);
|
|
}
|
|
}
|
|
|
|
// set flag to show that 5-way has been used
|
|
gUsedUpDown = true;
|
|
|
|
handled = true;
|
|
break;
|
|
}
|
|
|
|
case vchrRockerRight:
|
|
{
|
|
// Table is highlighted. Set focus on cancel button
|
|
if( selectedRow != -1 ) {
|
|
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
TblUnhighlightSelection(tableP);
|
|
FrmSetFocus(frmP, FrmGetObjectIndex(frmP, FileBrowserCancelButton));
|
|
PrvFormInit(frmP);
|
|
FrmDrawForm(frmP);
|
|
PrvDrawTableBorder(frmP);
|
|
selectedRow = -1;
|
|
}
|
|
handled = true;
|
|
break;
|
|
}
|
|
|
|
case vchrRockerLeft:
|
|
{
|
|
// Cancel button is highlighted. Set focus on table
|
|
if(selectedRow == -1) {
|
|
selectedRow = 0;
|
|
gTopIndex = 0;
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
PrvFormDeInit(frmP);
|
|
PrvFormInit(frmP);
|
|
FrmDrawForm(frmP);
|
|
PrvDrawTableBorder(frmP);
|
|
FrmNavObjectTakeFocus(frmP, FileBrowserFileTable);
|
|
TblSelectItem (tableP, selectedRow, 0);
|
|
}
|
|
handled = true;
|
|
break;
|
|
}
|
|
|
|
case vchrHardRockerCenter:
|
|
case vchrRockerCenter:
|
|
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
|
|
/* to get 5-way to sync with scrolling */
|
|
FileBrowserTestScrolling(tableP);
|
|
|
|
// Table is highlighted. Select file/folder
|
|
if(selectedRow != -1) {
|
|
|
|
selectedRow = selectedRow - gTopIndex;
|
|
gTopIndex = 0;
|
|
PrvSelectFile(TblGetRowID(tableP, selectedRow));
|
|
|
|
selectedRow = 0;
|
|
TblSelectItem (tableP, selectedRow, 0);
|
|
// Cancel button is highlighted. Go back to main form
|
|
} else {
|
|
gTopIndex = 0;
|
|
PrvListViewLoadTable(frmP, true);
|
|
FrmGotoForm(gReturnForm);
|
|
}
|
|
|
|
//after we sync 5-way with scrolling and select our file, we can set the flag to false
|
|
gScrolling = false;
|
|
|
|
handled = true;
|
|
break;
|
|
|
|
}
|
|
handled = true;
|
|
break;
|
|
|
|
case frmOpenEvent:
|
|
PrvFormInit(frmP);
|
|
|
|
FrmDrawForm(frmP);
|
|
PrvDrawTableBorder(frmP);
|
|
FrmNavObjectTakeFocus(frmP, FileBrowserFileTable);
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
TblSelectItem (tableP, selectedRow, 0);
|
|
|
|
// Restore the insertion point position.
|
|
handled = true;
|
|
break;
|
|
|
|
case ctlSelectEvent:
|
|
switch(eventP->data.ctlSelect.controlID)
|
|
{
|
|
case FileBrowserCancelButton:
|
|
FrmGotoForm(gReturnForm);
|
|
handled = true;
|
|
break;
|
|
}
|
|
break;
|
|
case sclRepeatEvent:
|
|
{
|
|
tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
gTopIndex += (eventP->data.sclRepeat.newValue - eventP->data.sclRepeat.value);
|
|
|
|
PrvListViewLoadTable(frmP, true);
|
|
TblUnhighlightSelection(tableP);
|
|
TblRedrawTable(tableP);
|
|
TblSelectItem (tableP, 0, 0);
|
|
|
|
//Show that scrolling has been used
|
|
gScrolling = true;
|
|
|
|
handled = false;
|
|
break;
|
|
}
|
|
case frmUpdateEvent:
|
|
PrvDrawTableBorder(frmP);
|
|
|
|
break;
|
|
|
|
case frmCloseEvent:
|
|
PrvFormDeInit();
|
|
selectedRow = 0;
|
|
gTopIndex = 0;
|
|
handled = false;
|
|
break;
|
|
|
|
case tblEnterEvent:
|
|
break;
|
|
|
|
case tblSelectEvent:
|
|
if( gFileCount > eventP->data.tblSelect.row )
|
|
{
|
|
gTopIndex = 0;
|
|
PrvSelectFile(TblGetRowID(eventP->data.tblSelect.pTable, eventP->data.tblSelect.row));
|
|
|
|
//after we select our file, we can set the scrolling flag to false
|
|
gScrolling = false;
|
|
|
|
handled = true;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserTestScrolling
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
void FileBrowserTestScrolling(TablePtr tableP)
|
|
{
|
|
|
|
/* If scrolling has been used, the focus is moved to the top item in the frame */
|
|
if (gScrolling == true) {
|
|
selectedRow = gTopIndex;
|
|
TblSelectItem (tableP, selectedRow, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserSetCallback
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
void FileBrowserSetCallback(FileBrowserCallback callback, UInt32 formID)
|
|
{
|
|
gCallback = callback;
|
|
gReturnForm = formID;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserIsCallbackSet
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
Boolean FileBrowserIsCallbackSet()
|
|
{
|
|
return (gCallback)?true:false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserIsReturnFormSet
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
Boolean FileBrowserIsReturnFormSet()
|
|
{
|
|
return (gReturnForm)?true:false;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserRefresh
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
void FileBrowserRefresh()
|
|
{
|
|
FormType *frmP = FrmGetActiveForm();
|
|
// Empty the current database
|
|
PrvEmptyDB();
|
|
|
|
// Load new files
|
|
gRowCount = 0;
|
|
gTopIndex = 0;
|
|
gFileCount = 0;
|
|
gVolumeCount = 0;
|
|
gCurrentVolume = 0;
|
|
*gCurrentPath = NULL;
|
|
*gCurrentFile = NULL;
|
|
|
|
// Redraw the form
|
|
if( frmP )
|
|
{
|
|
PrvFormInit(frmP);
|
|
FrmDrawForm(frmP);
|
|
PrvDrawTableBorder(frmP);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvSelectFile
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvSelectFile(UInt16 index)
|
|
{
|
|
MemHandle h;
|
|
FileBrowserFileInfo fileInfo;
|
|
FormType * frmP = FrmGetActiveForm();
|
|
|
|
// Check for error. Will also catch empty SD card.
|
|
if(PrvGetRecord(index, &fileInfo, &h) != errNone)
|
|
return;
|
|
|
|
if( fileInfo.attribute & vfsFileAttrDirectory )
|
|
{
|
|
if( !StrCompare("..", fileInfo.fileName) )
|
|
{
|
|
// One directory above
|
|
UInt32 strLen = StrLen(gCurrentPath);
|
|
// Skip last '/' <- always there
|
|
strLen -= 2;
|
|
while( gCurrentPath[strLen--] != '\\' ) {}
|
|
// Don't delete the first '/'
|
|
strLen += 2;
|
|
gCurrentPath[strLen] = NULL;
|
|
}
|
|
else
|
|
{
|
|
// One directory below
|
|
StrCat(gCurrentPath, fileInfo.fileName);
|
|
StrCat(gCurrentPath, "\\");
|
|
}
|
|
|
|
PrvReleaseRecord(index, h);
|
|
|
|
// Clean up database
|
|
PrvEmptyDB();
|
|
|
|
// Enumerate with the new path
|
|
PrvEnumerate();
|
|
|
|
// Display the path
|
|
{
|
|
FieldType *fieldP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserPathField));
|
|
SetFieldTextFromStr(fieldP, gCurrentPath, false);
|
|
}
|
|
|
|
// Reload the table
|
|
PrvListViewLoadTable(frmP, true);
|
|
|
|
FrmDrawForm(frmP);
|
|
|
|
PrvDrawTableBorder(frmP);
|
|
}
|
|
else
|
|
{
|
|
StrCopy(gCurrentFile, fileInfo.fileName);
|
|
PrvReleaseRecord(index, h);
|
|
|
|
// Play it!
|
|
if( gCallback ) {
|
|
gCallback(gCurrentVolume, gCurrentPath, gCurrentFile);
|
|
}
|
|
if( gReturnForm ) {
|
|
FrmGotoForm(gReturnForm);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvFormInit
|
|
*
|
|
* DESCRIPTION: This routine initialize the File Browser form.
|
|
*
|
|
* PARAMETERS: frmP - Pointer to the form.
|
|
*
|
|
* RETURNED: Error Code.
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Err PrvFormInit(FormType *frmP)
|
|
{
|
|
Err err = errNone;
|
|
UInt32 volumeIterator;
|
|
Boolean enumerate = false;
|
|
LocalID dbId;
|
|
|
|
if( !gDB )
|
|
{
|
|
// Open the database
|
|
dbId = DmFindDatabase(fbCardNumber, fbDBName);
|
|
if( dbId )
|
|
{
|
|
// If exists open it
|
|
gDB = DmOpenDatabase(fbCardNumber, dbId, dmModeReadWrite);
|
|
if(!gDB) {
|
|
err = DmGetLastErr();
|
|
goto Done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Else create the database
|
|
err = DmCreateDatabase(fbCardNumber, fbDBName, fbCreatorID, 'temp', false);
|
|
if (err != errNone) return err;
|
|
|
|
dbId = DmFindDatabase(fbCardNumber, fbDBName);
|
|
if( !dbId ) {
|
|
err = DmGetLastErr();
|
|
goto Done;
|
|
}
|
|
|
|
gDB = DmOpenDatabase(fbCardNumber, dbId, dmModeReadWrite);
|
|
if( !gDB ) {
|
|
err = DmGetLastErr();
|
|
goto Done;
|
|
}
|
|
|
|
// Need to enumerate the files
|
|
enumerate = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the first card if no volume selected
|
|
//
|
|
if( !gCurrentVolume )
|
|
{
|
|
volumeIterator = vfsIteratorStart;
|
|
err = VFSVolumeEnumerate(&gCurrentVolume, &volumeIterator);
|
|
if( err == expErrEnumerationEmpty ) {
|
|
gCurrentVolume = 0;
|
|
}
|
|
enumerate = true;
|
|
}
|
|
|
|
//
|
|
// Set path to the root if not set
|
|
//
|
|
if( !(*gCurrentPath) )
|
|
{
|
|
StrCopy((Char*)gCurrentPath, "\\");
|
|
enumerate = true;
|
|
}
|
|
|
|
//
|
|
// No file selected for now
|
|
//
|
|
*gCurrentFile = NULL;
|
|
|
|
//
|
|
// Load the files in the Database if needed
|
|
//
|
|
if( enumerate ) {
|
|
PrvEnumerate();
|
|
}
|
|
|
|
//
|
|
// Load the bitmaps
|
|
//
|
|
{
|
|
MemHandle h;
|
|
BitmapType* bmpP;
|
|
Coord width, height;
|
|
WinHandle winH = WinGetDrawWindow();
|
|
Err err;
|
|
|
|
h = DmGet1Resource(bitmapRsc, FolderBitmapFamily);
|
|
bmpP = (BitmapType*)MemHandleLock(h);
|
|
BmpGetDimensions(bmpP, &width, &height, 0);
|
|
gFolderWinH = WinCreateOffscreenWindow(width, height, nativeFormat, &err);
|
|
WinSetDrawWindow(gFolderWinH);
|
|
WinDrawBitmap(bmpP, 0, 0);
|
|
MemHandleUnlock(h);
|
|
DmReleaseResource(h);
|
|
|
|
h = DmGet1Resource(bitmapRsc, DocumentBitmapFamily);
|
|
bmpP = (BitmapType*)MemHandleLock(h);
|
|
BmpGetDimensions(bmpP, &width, &height, 0);
|
|
gDocumentWinH = WinCreateOffscreenWindow(width, height, nativeFormat, &err);
|
|
WinSetDrawWindow(gDocumentWinH);
|
|
WinDrawBitmap(bmpP, 0, 0);
|
|
MemHandleUnlock(h);
|
|
DmReleaseResource(h);
|
|
|
|
WinSetDrawWindow(winH);
|
|
}
|
|
|
|
//
|
|
// Display the path
|
|
//
|
|
{
|
|
FieldType *fieldP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserPathField));
|
|
SetFieldTextFromStr(fieldP, gCurrentPath, false);
|
|
}
|
|
|
|
Done:
|
|
//
|
|
// Setup the table
|
|
//
|
|
PrvListViewInit(frmP);
|
|
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvFormDeInit
|
|
*
|
|
* DESCRIPTION: This routine de-initialize the File Browser form.
|
|
*
|
|
* PARAMETERS: frmP - Pointer to the form.
|
|
*
|
|
* RETURNED: None.
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvFormDeInit()
|
|
{
|
|
// Release the offscreen windows
|
|
if( gFolderWinH ) {
|
|
WinDeleteWindow(gFolderWinH, false);
|
|
gFolderWinH = 0;
|
|
}
|
|
|
|
if( gDocumentWinH ) {
|
|
WinDeleteWindow(gDocumentWinH, false);
|
|
gDocumentWinH = 0;
|
|
}
|
|
|
|
// Close the database
|
|
if( gDB ) {
|
|
DmCloseDatabase(gDB);
|
|
gDB = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvEnumerate
|
|
*
|
|
* DESCRIPTION: .
|
|
*
|
|
* PARAMETERS: None.
|
|
*
|
|
* RETURNED: N/A.
|
|
*
|
|
***********************************************************************/
|
|
|
|
Err PrvEnumerate()
|
|
{
|
|
Err err = errNone;
|
|
FileRef dirRef = 0;
|
|
FileRef fileRef = 0;
|
|
FileInfoType fileInfo;
|
|
UInt32 fileSize = 0;
|
|
UInt32 fileIterator = 0;
|
|
|
|
Char *fileName = (Char*)MemPtrNew(MAX_FILENAME_LENGTH);
|
|
Char *fileName2 = (Char*)MemPtrNew(MAX_FILENAME_LENGTH);
|
|
|
|
fileInfo.nameP = fileName;
|
|
fileInfo.nameBufLen = MAX_FILENAME_LENGTH;
|
|
|
|
// Clean the database
|
|
PrvEmptyDB();
|
|
|
|
// If not the root, add UP directory
|
|
if( StrCompare( "\\", gCurrentPath) )
|
|
{
|
|
StrCopy( fileName, "..");
|
|
fileInfo.attributes = vfsFileAttrDirectory;
|
|
PrvAddRecord(&fileInfo, 0);
|
|
}
|
|
|
|
// Open at the current volume and path
|
|
err = VFSFileOpen(gCurrentVolume, gCurrentPath, vfsModeRead, &dirRef);
|
|
if( err == errNone )
|
|
{
|
|
fileIterator = vfsIteratorStart;
|
|
while( fileIterator != vfsIteratorStop )
|
|
{
|
|
err = VFSDirEntryEnumerate(dirRef, &fileIterator, &fileInfo);
|
|
if( err == errNone )
|
|
{
|
|
if( ! (fileInfo.attributes & UNWANTED_FILES) )
|
|
{
|
|
if( fileInfo.attributes & vfsFileAttrDirectory ) {
|
|
PrvAddRecord(&fileInfo, 0);
|
|
} else {
|
|
StrCopy(fileName2, gCurrentPath);
|
|
StrCat(fileName2, fileInfo.nameP);
|
|
err = VFSFileOpen(gCurrentVolume, fileName2, vfsModeRead, &fileRef);
|
|
err = VFSFileSize(fileRef, &fileSize);
|
|
PrvAddRecord(&fileInfo, fileSize);
|
|
err = VFSFileClose(fileRef);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VFSFileClose( dirRef );
|
|
}
|
|
|
|
MemPtrFree(fileName);
|
|
MemPtrFree(fileName2);
|
|
|
|
|
|
gFileCount = DmNumRecords(gDB);
|
|
|
|
PrvDBSort();
|
|
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvDrawTableBorder
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED: N/A
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvDrawTableBorder(FormType *frmP)
|
|
{
|
|
RectangleType bounds;
|
|
TablePtr tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
|
|
TblGetBounds(tableP, &bounds);
|
|
WinDrawRectangleFrame(menuFrame, &bounds);
|
|
|
|
}
|
|
|
|
#pragma mark ---------- File Browser DB Functions ----------
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: FileBrowserDeleteDB
|
|
*
|
|
* DESCRIPTION: This routine should be called when the app stops.
|
|
* It deletes the temporary database.
|
|
*
|
|
* PARAMETERS: None.
|
|
*
|
|
* RETURNED: Error Code.
|
|
*
|
|
***********************************************************************/
|
|
|
|
Err FileBrowserDeleteDB()
|
|
{
|
|
LocalID dbID;
|
|
UInt16 cardNo;
|
|
|
|
Err err = errNone;
|
|
|
|
if(!gDB)
|
|
{
|
|
// Open the database
|
|
dbID = DmFindDatabase(fbCardNumber, fbDBName);
|
|
if( dbID )
|
|
{
|
|
// If exists open it
|
|
gDB = DmOpenDatabase(fbCardNumber, dbID, dmModeReadWrite);
|
|
if(!gDB) {
|
|
err = DmGetLastErr();
|
|
return err;
|
|
}
|
|
}
|
|
else
|
|
return err;
|
|
}
|
|
|
|
err = DmOpenDatabaseInfo(gDB, &dbID, 0, 0, &cardNo, 0);
|
|
err = DmCloseDatabase(gDB);
|
|
err = DmDeleteDatabase(cardNo, dbID);
|
|
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvEmptyDB
|
|
*
|
|
* DESCRIPTION: This routine deletes all the records of the temp database.
|
|
*
|
|
* PARAMETERS: None.
|
|
*
|
|
* RETURNED: Error Code.
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Err PrvEmptyDB()
|
|
{
|
|
Err err = errNone;
|
|
UInt16 index = DmNumRecords(gDB);
|
|
|
|
while (index--)
|
|
{
|
|
err = DmRemoveRecord(gDB, index);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvAddRecord
|
|
*
|
|
* DESCRIPTION: This routine adds a record to the temp database
|
|
*
|
|
* PARAMETERS: fileInfoP - Pointer to a FileInfo Structure
|
|
*
|
|
* RETURNED: Error Code
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Err PrvAddRecord(FileInfoType* fileInfoP, UInt32 fileSize)
|
|
{
|
|
|
|
Err err = errNone;
|
|
void* memLockP = NULL;
|
|
MemHandle recordHandle = NULL;
|
|
UInt32 recordSize = 0;
|
|
UInt16 recordIndex = dmMaxRecordIndex;
|
|
UInt32 offset = 0;
|
|
FileBrowserFileInfo fbFileInfo;
|
|
|
|
// Local store
|
|
fbFileInfo.selected = false;
|
|
fbFileInfo.attribute = fileInfoP->attributes;
|
|
fbFileInfo.fileName = fileInfoP->nameP;
|
|
fbFileInfo.fileSize = fileSize;
|
|
|
|
recordSize = (StrLen(fbFileInfo.fileName)+1);
|
|
|
|
recordHandle = DmNewRecord(gDB, &recordIndex, recordSize + sizeof(UInt32) + sizeof(UInt16) + sizeof(Boolean));
|
|
if( !recordHandle )
|
|
{
|
|
err = DmGetLastErr();
|
|
return err;
|
|
}
|
|
|
|
memLockP = MemHandleLock(recordHandle);
|
|
|
|
// Write selection
|
|
offset = 0;
|
|
err = DmWrite( memLockP, offset, &fbFileInfo.selected, sizeof(Boolean));
|
|
if(err) goto Done;
|
|
|
|
offset += sizeof(Boolean);
|
|
err = DmWrite( memLockP, offset, &fbFileInfo.attribute, sizeof(UInt16));
|
|
if(err) goto Done;
|
|
|
|
offset += sizeof(UInt16);
|
|
err = DmWrite( memLockP, offset, &fbFileInfo.fileSize, sizeof(UInt32));
|
|
if(err) goto Done;
|
|
|
|
offset += sizeof(UInt32);
|
|
err = DmWrite( memLockP, offset, fbFileInfo.fileName, recordSize);
|
|
if(err) goto Done;
|
|
|
|
Done:
|
|
MemHandleUnlock(recordHandle);
|
|
err = DmReleaseRecord(gDB, recordIndex, true);
|
|
|
|
if( err )
|
|
{
|
|
DmRemoveRecord(gDB, recordIndex);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvGetRecord
|
|
*
|
|
* DESCRIPTION: This routine returns the file info for the given index
|
|
*
|
|
* PARAMETERS: index - File index in the database
|
|
* fileInfoP - File info Ptr
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Err PrvGetRecord(UInt16 index, FileBrowserFileInfo* fileInfoP, MemHandle* hP)
|
|
{
|
|
Err err = errNone;
|
|
MemHandle recH;
|
|
UInt8 *recP = NULL;
|
|
|
|
recH = DmQueryRecord(gDB, index);
|
|
if (recH == NULL)
|
|
{
|
|
err = DmGetLastErr();
|
|
goto Done;
|
|
}
|
|
else *hP = recH;
|
|
|
|
recP = (UInt8 *)MemHandleLock(recH);
|
|
if (recP == NULL)
|
|
{
|
|
err = memErrChunkNotLocked;
|
|
goto Done;
|
|
}
|
|
|
|
fileInfoP->selected = (Boolean)*recP;
|
|
recP += sizeof(Boolean);
|
|
fileInfoP->attribute = MisalignedReadBEUInt16(recP, 0);
|
|
recP += sizeof(UInt16);
|
|
fileInfoP->fileSize = MisalignedReadBEUInt32(recP, 0);
|
|
recP += sizeof(UInt32);
|
|
fileInfoP->fileName = (Char*)recP;
|
|
|
|
Done:
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvReleaseRecord
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvReleaseRecord(UInt16 index, MemHandle h)
|
|
{
|
|
index = 0;// To prevent some annoying warnings ( Ignore )
|
|
MemHandleUnlock(h);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION:
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNED:
|
|
*
|
|
***********************************************************************/
|
|
|
|
static Int16 PrvDBCompareRecords( Char* r1P, Char* r2P,
|
|
Int16 UNUSED_PARAM(param), SortRecordInfoType* UNUSED_PARAM(info1),
|
|
SortRecordInfoType* UNUSED_PARAM(info2), MemHandle UNUSED_PARAM(appInfoH))
|
|
{
|
|
Int16 result;
|
|
FileBrowserFileInfo rec1, rec2;
|
|
|
|
rec1.selected = (Boolean)*r1P;
|
|
r1P += sizeof(Boolean);
|
|
rec1.attribute = MisalignedReadBEUInt16(r1P, 0);
|
|
r1P += sizeof(UInt16) + sizeof(UInt32);
|
|
rec1.fileName = (Char*)r1P;
|
|
|
|
rec2.selected = (Boolean)*r2P;
|
|
r2P += sizeof(Boolean);
|
|
rec2.attribute = MisalignedReadBEUInt16(r2P, 0);
|
|
r2P += sizeof(UInt16) + sizeof(UInt32);
|
|
rec2.fileName = (Char*)r2P;
|
|
|
|
|
|
// First check to display the folder first
|
|
if (rec1.attribute & vfsFileAttrDirectory)
|
|
{
|
|
if (!(rec2.attribute & vfsFileAttrDirectory))
|
|
return -1;
|
|
}
|
|
else if (rec2.attribute & vfsFileAttrDirectory)
|
|
return 1;
|
|
|
|
// Alphabetize;
|
|
result = TxtCompare( rec1.fileName, // const Char *s1
|
|
0xFFFF, // UInt16 s1Len,
|
|
NULL, // UInt16 *s1MatchLen,
|
|
rec2.fileName, // const Char *s2,
|
|
0xFFFF, // UInt16 s2Len,
|
|
NULL); // UInt16 *s2MatchLen
|
|
return result;
|
|
}
|
|
/************************************************************
|
|
*
|
|
* FUNCTION:
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*************************************************************/
|
|
|
|
static void PrvDBSort()
|
|
{
|
|
DmInsertionSort(gDB, (DmComparF *)&PrvDBCompareRecords, 0);
|
|
}
|
|
|
|
#pragma mark ---------- File Browser List View ----------
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvListViewInit
|
|
*
|
|
* DESCRIPTION: This routine initializes the table
|
|
*
|
|
* PARAMETERS: frmP - Pointer to a form
|
|
*
|
|
* RETURNED: N/A
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvListViewInit(FormType *frmP)
|
|
{
|
|
UInt16 rowCount;
|
|
TablePtr tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
|
|
gRowCount = rowCount = TblGetNumberOfRows(tableP);
|
|
|
|
// Init the row elements
|
|
while( rowCount-- )
|
|
{
|
|
TblSetRowUsable(tableP, rowCount, false);
|
|
TblSetItemStyle(tableP, rowCount, FILE_COLUMN, customTableItem);
|
|
}
|
|
|
|
TblHasScrollBar(tableP, true);
|
|
TblSetColumnUsable(tableP, FILE_COLUMN, true);
|
|
TblSetCustomDrawProcedure(tableP, FILE_COLUMN, PrvListViewDrawFile);
|
|
|
|
// Load the table
|
|
PrvListViewLoadTable(frmP, false);
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvListViewDrawFile
|
|
*
|
|
* DESCRIPTION: This routine draws a file in the table
|
|
*
|
|
* PARAMETERS: tableP - Pointer to the table
|
|
* row - The row to draw
|
|
* column - The column to draw
|
|
* boundsP - Pointer to the element bound
|
|
*
|
|
* RETURNED: N/A
|
|
*
|
|
***********************************************************************/
|
|
|
|
static void PrvListViewDrawFile(void *tableP, Int16 row, Int16 column, RectangleType *boundsP)
|
|
{
|
|
UInt16 index;
|
|
MemHandle h;
|
|
FileBrowserFileInfo fileInfo;
|
|
WinHandle winH;
|
|
Char * ptr;
|
|
UInt16 titleLen;
|
|
Char text[32];
|
|
UInt32 fileSizeWidth = 0;
|
|
Err err = errNone;
|
|
|
|
column = 0; // ignore, to prevent some annoying warnings
|
|
index = TblGetRowID(tableP, row);
|
|
|
|
err = PrvGetRecord( index, &fileInfo, &h);
|
|
if( err ) goto Done;
|
|
|
|
// Draw icon
|
|
ptr = StrChr (fileInfo.fileName, linefeedChr);
|
|
titleLen = (ptr == NULL ? StrLen (fileInfo.fileName) : (UInt16) (ptr - fileInfo.fileName));
|
|
|
|
if( fileInfo.attribute & vfsFileAttrDirectory )
|
|
{
|
|
RectangleType rct;
|
|
|
|
winH = gFolderWinH;
|
|
|
|
WinGetWindowFrameRect(winH, &rct);
|
|
WinCopyRectangle(winH, 0, &rct, boundsP->topLeft.x, boundsP->topLeft.y + 1, winPaint);
|
|
}
|
|
else
|
|
{
|
|
RectangleType rct;
|
|
|
|
winH = gDocumentWinH;
|
|
|
|
WinGetWindowFrameRect(winH, &rct);
|
|
WinCopyRectangle(winH, 0, &rct, boundsP->topLeft.x, boundsP->topLeft.y + 1, winPaint);
|
|
|
|
}
|
|
|
|
if( !(fileInfo.attribute & vfsFileAttrDirectory) )
|
|
{
|
|
// Display the file size
|
|
if(fileInfo.fileSize > 1048576)
|
|
{
|
|
// Use the KB style (123.4 MB)
|
|
UInt32 mantissa = fileInfo.fileSize / 1048576;
|
|
UInt32 fraction = ( fileInfo.fileSize - mantissa * 1048576 ) / 104858;
|
|
|
|
StrPrintF(text, "%ld.%ld M", mantissa, fraction);
|
|
}
|
|
else if(fileInfo.fileSize > 1024)
|
|
{
|
|
// Use the KB style (123.4 KB)
|
|
UInt32 mantissa = fileInfo.fileSize / 1024;
|
|
UInt32 fraction = ( fileInfo.fileSize - mantissa * 1024 ) / 103;
|
|
|
|
StrPrintF(text, "%ld.%ld K", mantissa, fraction);
|
|
}
|
|
else
|
|
{
|
|
// Use the B style (24 B)
|
|
StrPrintF(text, "%ld B", fileInfo.fileSize);
|
|
}
|
|
|
|
// Get the length
|
|
fileSizeWidth = FntCharsWidth(text, StrLen(text));
|
|
WinDrawChars(text, StrLen(text), boundsP->topLeft.x + boundsP->extent.x - fileSizeWidth, boundsP->topLeft.y);
|
|
//fileSizeWidth + 4; // Give me some space
|
|
}
|
|
|
|
// Draw File Name
|
|
if( FntWidthToOffset (fileInfo.fileName, titleLen, boundsP->extent.x - 15 - fileSizeWidth, NULL, NULL) == titleLen)
|
|
{
|
|
WinDrawChars (fileInfo.fileName, titleLen, boundsP->topLeft.x + 15, boundsP->topLeft.y);
|
|
}
|
|
else
|
|
{
|
|
Int16 titleWidth;
|
|
titleLen = FntWidthToOffset (fileInfo.fileName, titleLen, boundsP->extent.x - 15 - fileSizeWidth - FntCharWidth (chrEllipsis), NULL, &titleWidth);
|
|
WinDrawChars (fileInfo.fileName, titleLen, boundsP->topLeft.x + 15, boundsP->topLeft.y);
|
|
WinDrawChar (chrEllipsis, boundsP->topLeft.x + 15 + titleWidth, boundsP->topLeft.y);
|
|
}
|
|
|
|
// Release the record
|
|
PrvReleaseRecord(index, h);
|
|
|
|
Done:
|
|
return;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* FUNCTION: PrvListViewLoadTable
|
|
*
|
|
* DESCRIPTION: This routine loads the table.
|
|
*
|
|
* PARAMETERS: frmP - Pointer to a form.
|
|
*
|
|
* RETURNED: N/A
|
|
*
|
|
***********************************************************************/
|
|
|
|
void PrvListViewLoadTable(FormType *frmP, Boolean redraw)
|
|
{
|
|
UInt16 row;
|
|
UInt16 rowCount;
|
|
UInt16 displayCount;
|
|
TablePtr tableP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileTable));
|
|
ScrollBarPtr barP = FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, FileBrowserFileScrollBar));
|
|
|
|
rowCount = TblGetNumberOfRows(tableP);
|
|
|
|
//If scrolling or 5-way have been used and there is only 1 file, reset gTopIndex
|
|
|
|
if (((gScrolling == true)||(gUsedUpDown == true)) && gFileCount == 1){
|
|
gTopIndex = 0;
|
|
|
|
}
|
|
|
|
displayCount = gFileCount - gTopIndex;
|
|
|
|
for(row = 0; row < gRowCount; row++)
|
|
{
|
|
if( row < displayCount )
|
|
{
|
|
TblSetRowID(tableP, row, row + gTopIndex);
|
|
TblSetRowUsable(tableP, row, true);
|
|
TblSetRowSelectable(tableP, row, true);
|
|
}
|
|
else
|
|
{
|
|
TblSetRowUsable(tableP, row, false);
|
|
TblSetRowSelectable(tableP, row, false);
|
|
}
|
|
}
|
|
|
|
if( redraw )
|
|
{
|
|
TblEraseTable(tableP);
|
|
TblDrawTable(tableP);
|
|
|
|
}
|
|
|
|
if( gFileCount <= gRowCount )
|
|
{
|
|
SclSetScrollBar(barP, 0, 0, 0, gRowCount);
|
|
}
|
|
else
|
|
{
|
|
|
|
SclSetScrollBar(barP, gTopIndex, 0, gFileCount - gRowCount, gRowCount);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|