TDirectory::GetFiles listing ignoring case on iOS (FMX, C++) - firemonkey

The code below lists files that have extension .cfg and it works fine on Win32. But, on iOS if i have a file that a user named with caps for the extension (e.g. test.CFG) then i miss it. I found this post using Delphi that might work using TDirectory::TFilterPredicate but i don't know how to implement in C++Builder.
TStringDynArray list;
TSearchOption searchOption;
UnicodeString DocsPath;
int lenDocsFolder;
DocsPath = System::Ioutils::TPath::GetDocumentsPath();
lenDocsFolder = DocsPath.Length();
searchOption = TSearchOption::soTopDirectoryOnly;
try
{
list = TDirectory::GetFiles(DocsPath, "*.cfg", searchOption);
}
catch (...)
{
ShowMessage("Incorrect path or search mask");
return;
}
I suppose i can just run a *.cfg block of code followed by a *.CFG but i'm hoping there is a cleaner approach.

Sorry, but I'm not used to C++. But this applies to both C++ and Delphi.
You are calling:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption): TStringDynArray;
If you instead call this overloaded version:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption;
const Predicate: TFilterPredicate): TStringDynArray;
you should be able to get what you need.
The TFilterPredicate type is defined as:
TFilterPredicate = reference to function(
const Path: string;
const SearchRec: TSearchRec): Boolean;
and should be the correct way to override the way files are matched.

I tried the Using a Lambda Expression from the link Remy posted in comment. I got an E2188 Expression syntaxerror until i disabled the classic Borland compiler. The code works great for simple predicate (on both Win32 and iOS).
String ext(".cfg");
files = TDirectory::GetFiles(CalcPath,
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
Now, how do i modify the extension string to return results for both .cfg and .CFG at same time?
String ext(".cfg"); // works fine
String ext(".cfg;.CFG"); // finds nothing

Related

Updating display of directory/folder path in MFC File-Open dialog [duplicate]

I'm trying to make a 'Save As' dialog with an event that would change the default path based on the type of file we choose from the filters combo box. The problem is, all the examples I've seen execute the code on result IDOK or IDCANCEL while I'd need the code to be executed while the dialog is still opened.
Also, is there any way to differentiate between what filter has been chosen if the filters have the same type? The GetFileExt() method just returns the extension but I have no way of telling if it was the first .my filter or the template .my filter.
I've seen something like LPOFNHOOKPROC but there was no example of how would I even use it and I'm not sure whether it would even solve my problem or not.
void CMyClass::OnFileOpen()
{
CString pathNam;
CString fileName;
TCHAR szFilters[]= _T("MyType Files (*.my)|*.my|Template MyType (*.my)|*.my||");
CFileDialog fileDlg(TRUE, _T("my"), _T("*.my"),
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
if(fileDlg.DoModal() == IDOK)
{
pathName = fileDlg.GetPathName();
fileName = fileDlg.GetFileTitle();
}
}
EDIT:
I am now able to get the specific filter that's been chosen by getting the OFN and checking the nFilterIndex value. So the remaining problem is whether I can update the path based on the chosen file format?
EDIT2:
I've found the OnChangeType method and overloaded it in the subclass and it indeed executes the method and the code within, but when I try to update the file path I get an access violation:
void TFileDialogExt::OnTypeChange()
{
LPWSTR buff = L"C:\\TEST\\template.my";
if(m_pOFN->nFilterIndex == 2)
m_ofn.lpstrFile = buff;
}
Basically you have to subclass CFileDialog and handle its CFileDialog::OnTypeChange method.
But, as suggested by Microsoft: you'd better use a new Common Item Dialog instead.
I did some research about this and found some useful questions:
Programmatically pre-select using IFileDialog in C++
How to use SHCreateItemFromParsingName with names from the shell namespace?
Also, have a look at: SHCreateItemFromParsingName.
Here is a sample OnTypeChange handler:
void CMyFileDialog::OnTypeChange()
{
{
IFileOpenDialog* pfod = NULL;
HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->QueryInterface(IID_PPV_ARGS(&pfod));
if (SUCCEEDED(hr))
{
IShellItem* psiInitialDir;
CString strFolder = L"d:\\";
hr = SHCreateItemFromParsingName(strFolder.GetString(), NULL, IID_PPV_ARGS(&psiInitialDir));
if(SUCCEEDED(hr))
{
pfod->SetFolder(psiInitialDir);
}
}
}
CFileDialog::OnTypeChange();
}
My code uses a hard coded path for testing purposes, but you should now be able to complete your code:
Determine which path you want to use based on the currently selected filter index.
Use similar logic as here to navigate to that folder.

xamarin non-english dot and comma calculations (Xamarin multi-language support)

We are developing a mobile application using Xamarin cross platform development for Android and iOS, which is reading data from a Bluetooth device that transfers data as a float i.e. 12.22 and it will support multiple languages.
When it's set to English all our calculations are fine, but when set to non-english the calculations go completely wrong. I know what is wrong in non-english languages it's treating the "." as an "," which is means a 12.22 becomes 12,22. Therefore, screwing up our calculations.
I have found similar problems, but they force the complete language to English which means we lose the translations and other fixes look very complex for what must be a simple fix.
Is there a easy fix to this problem, like setting a flag in the Xamarin multi-language support
Update :
With the BLE transfer code, we can see the string but when it convert it we get 6000000 for French or 60 for English.
private async Task<double>
GetDatastoreValue(Plugin.BLE.Abstractions.Contracts.IService service, string param)
{
try
{
var datastore_param_char = await service.GetCharacteristicAsync(Guid.Parse(datastore_param_uid));
var datastore_param_val = await service.GetCharacteristicAsync(Guid.Parse(datastore_value_uid));
await datastore_param_char.WriteAsync(Encoding.ASCII.GetBytes(param));
byte[] result = await datastore_param_val.ReadAsync();
string rslt = Encoding.ASCII.GetString(result);
Debug.WriteLine("GetDatastoreValue -> result " + result);
double val = Convert.ToDouble(rslt);
Debug.WriteLine("GetDatastoreValue -> val -> "+ val);
return val;
}
catch
{
return 0.0;
}
}
instead of using this
double val = Convert.ToDouble(rslt);
do this
double val = Double.Parse(rslt, CultureInfo.InvariantCulture);
this will force it to evaluate "123.45" using the decimal separator, regardless of what the user's local culture might be set to

How to convert C++ SaveFileDiolog info to LPCTSTR

I've been working on a c++ app.. and I figured out how to grab the directory name from a SaveFileDialog and combine that with text for a saving a bunch of files to the same folder, but the code ends up unassigned when I try to convert my new FileWithPathName to an LPCTSTR.
I have searched all over this site and can't seem to find a really clear example of what I am looking for. If someone can direct me to a link that is clear on this or tell me what am I doing wrong that would be great. ;-)
FileInfo^ fi = gcnew FileInfo(saveFileDialog1->FileName);
String^ fileNameWithPath = gcnew String(fi->DirectoryName) + "newName.txt";
//LPCWSTR lfileNameWithPath = (LPCWSTR)(pfileNameWithPath[0]); // get temporary LPSTR // fails to get initialized
//LPCTSTR lfileNameWithPath = (LPCTSTR)(Marshal::StringToHGlobalAnsi(fileNameWithPath)).ToPointer(); // data returned like Chinese characters. epic fail
There are couple of different methods to make that conversion. You can use:
#include <msclr/marshal.h>
using namespace msclr::interop;
using namespace System;
String^ fileNameWithPath = gcnew String(fi->DirectoryName) + "newName.txt";
marshal_context context;
LPCTSTR lfileNameWithPath = context.marshal_as<LPCTSTR>(fileNameWithPath);
more here

How can I reuse code between Javascript macros and minimize work done within the macros?

I currently have two macros that are part of a (very limited-audience) plugin I'm developing, that both look basically like:
(function(){
exports.name = "name";
exports.params = [
{name: "value"}
];
function get(tiddler) {
// return some contents of some tiddler fields according to some rule
}
function parse(data) {
// convert string to some kind of useful object
}
function logic(x, y) {
// determine whether the two objects correspond in some way
};
function format(data, title) {
// produce WikiText for a link with some additional decoration
};
exports.run = function(value) {
value = parse(value);
var result = [];
this.wiki.each(function(tiddler, title) {
var data = get(tiddler);
if (data !== undefined && logic(value, parse(data))) {
result.push(format(data, title));
}
});
return result.join(" | ");
};
})();
So they're already fairly neatly factored when considered individually; the problem is that only the core logic is really different between the two macros. How can I share the functions get, logic and format between the macros? I tried just putting them in a separate tiddler, but that doesn't work; when the macros run, TW raises an error claiming that the functions are "not defined". Wrapping each function as its own javascript macro in a separate tiddler, e.g.
(function(){
exports.name = "get";
exports.params = [
{name: "tiddler"}
];
exports.run = function(tiddler) {
// return some contents of some tiddler fields according to some rule
}
})();
also didn't help.
I'd also like to set this up to be more modular/flexible, by turning the main get/parse/logic/format process into a custom filter, then letting a normal filter expression take care of the iteration and using e.g. the widget or <> macro to display the items. How exactly do I set this up? The documentation tells me
If the provided filter operators are not enough, a developer can add
new filters by adding a module with the filteroperator type
but I can't find any documentation of the API for this, nor any examples.
How can I share the functions get, logic and format between the macros?
You can use the Common/JS standard require('<tiddler title>') syntax to access the exports of another tiddler. The target tiddler should be set up as a JS module (ie, the type field set to application/javascript and the module-type field set to library). You can see an example here:
https://github.com/Jermolene/TiddlyWiki5/blob/master/core/modules/widgets/count.js#L15
I'd also like to set this up to be more modular/flexible, by turning the main get/parse/logic/format process into a custom filter, then letting a normal filter expression take care of the iteration and using e.g. the widget or <> macro to display the items. How exactly do I set this up?
The API for writing filter operators isn't currently documented, but there are many examples to look at:
https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/filters

Where is code refers to /proc/PID/maps?

I what to observe kernel code to print /proc/PID/maps but can't find this. Could anybody tell me where this code is located
The procfs code can be found in fs/proc/ subdirectory. If you open fs/proc/base.c, you can find two very similar arrays - tgid_base_stuff and tid_base_stuff. They both register file operations functions for files inside of /proc/PID/ and /proc/PID/TID/ respectivly. So you're more interested in the first one. Find the one that registers "maps" file, it looks like this:
REG("maps", S_IRUGO, proc_pid_maps_operations),
So the structure describing file operations on this file is called proc_pid_maps_operations. This function is defined in two places - fs/proc/task_mmu.c and fs/proc/task_nommu.c. Which one is actually used depends on your kernel configuration but it's most likely the first one.
Inside of task_mmu.c, you can find the structure definition:
const struct file_operations proc_pid_maps_operations =
{
.open = pid_maps_open,
.read = seq_read,
.llseek = seq_lseek,
.release = proc_map_release,
};
So when /proc/PID/maps is opened, the kernel will use pid_maps_open function, which registers another set of operations:
static const struct seq_operations proc_pid_maps_op = {
.start = m_start,
.next = m_next,
.stop = m_stop,
.show = show_pid_map
};
So you're interested in show_pid_map function, which only calls show_map function which in turn calls show_map_vma (all in the same file).
It's the show_pid_map() function in fs/proc/task_mmu.c (provided your system uses an MMU, which is the case of most non-embedded systems).
In general, the code for files under /proc/ can be cause under fs/procfs.

Resources