Using the correct codes with setlocale - mfc

I have had a look at setlocale but I am struggling to find what I am looking for.
In my code I have:
void CMeetingScheduleAssistantApp::SetLocale()
{
CString strLang[NUM_LANGUAGES] =
{
_T("eng"), _T("deu"), _T("esp"), _T("ita"),
_T("plk"), _T("fra"), _T("ptb"), _T("nld"),
_T("sve"), _T("slv"), _T("csy"), _T("fin"),
_T("dan"), _T("ukr"), _T("rus"),
_T("eng"), /*_T("fpo") Tagalog */
_T("eng"), /* Haitian Creole */
_T("eng"), /* Afrikaans */
_T("sqi"),
_T("chs"), /* Chinese (Simplified) */
_T("hrv"),
_T("trk"),
_T("eng"), /* Twi */
_T("swk"), // AJT v11.3.4
_T("eng"), // _T("eti") Estonian AJT v12.0.5
_T("rom"), // Romanian AJT v12.0.8
_T("ell"), // Greek AJT v13.0.0
_T("bgr"), // Bulgarian AJT v13.0.2
_T("eng"), // Malagasy AJT v14.0.4
_T("ara"), // Arabic AJT v16.0.0
_T("ind"), // Indonesian AJT v16.0.2
_T("hin"), // Hindi AJT v16.0.7
_T("tai"), // Tamil AJT v16.1.0
_T("vit"), // Vietnamese v16.1.1
_T("eng"), // Zulu AJT v16.1.6
_T("eng"), // Gun AJT v17.0.9
_T("ln-CG"), // Lingala v17.0.9
_T("ptg") // Portuguese Portugal v17.1.0
// Add more languages here
};
_tsetlocale(LC_ALL, strLang[m_eLanguage - LANGUAGE_ENGLISH]);
}
This has done and always works OK. Dates format correct after making this call.
But looking at the links provided with the aforementioned help topic I can't find codes like ptb etc. listed. Only pt-BR.
I assume my codes are still valid and are they documented anywhere?

setlocale expects a locale name as documented under Locale Names, Languages, and Country/Region Strings. A locale can be identified by locale name:
A locale name is based on the language tagging conventions of RFC 4646 (Windows Vista and later), and is represented by LOCALE_SNAME. Generally, the pattern <language>-<REGION> is used. Here, language is a lowercase ISO 639 language code. The codes from ISO 639-1 are used when available. Otherwise, codes from ISO 639-2/T are used.
[...]
If the locale is a neutral locale (no region), the LOCALE_SNAME value follows the pattern <language>.
A complete list of ISO 639-2 three-letter language codes is published at wikipedia.

Related

Can't change console application window title with virtual terminal sequences

I read this article by Microsoft about using of console virtual terminal sequences.
I followed this sequence to change the window title:
ESC ] 2 ; <string> BEL
I also tried:
ESC ] 0 ; <string> BEL
But it doesn't change the title.
This is my code:
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
int main()
{
// https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
// Set output mode to handle virtual terminal sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
DWORD dwMode = 0;
if (!GetConsoleMode(hOut, &dwMode))
{
return GetLastError();
}
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hOut, dwMode))
{
return GetLastError();
}
// Try some Set Graphics Rendition (SGR) terminal escape sequences
wprintf(L"hello");
wprintf(L"\x1b]2;titel\x07");
return 0;
}
It doesn't change the console window title.
The Microsoft document suggests:
Note that these sequences are OSC “Operating system command” sequences, and not a CSI like many of the other sequences listed, and as such starts with “\x1b]”, not “\x1b[”. As OSC sequences, they are ended with a String Terminator represented as and transmitted with ESC \ (0x1B 0x5C). BEL (0x7) may be used instead as the terminator, but the longer form is preferred.
It wouldn't be the first time MS didn't implement something. Try Esc \ - it's worked for me.
That said, I have noticed during debugging that the window title doesn't change immediately and since you terminate the program right after the sequence, you might not be seeing the effect.

WIN32_FIND_DATA equivalent in Linux C++

What is the equivalent for WIN32_FIND_DATA in Linux C++?
WIN32_FIND_DATA fileInfo;
WIN32_FIND_DATA is a datatype for Windows specification.
When I change to Linux Centos 7 with C++11 then I need to find the equivalent to it because there are several method in WIN32_FIND_DATA do not support in Linux like.
fileInfo.cFileName
C++17 has filesystem.
Example:
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
fs::path p { "/usr/lib/" };
for (auto& entry : p)
{
// do something with entry
}
return 0;
}
It is based on the file system functionality from the Boost library so you could use that with older compilers.
The stat struct defined as: (its the closest to what you require)
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
Otherwise you have to build it from scratch and GNU Core Utils can help.

`Too many initializers` for for array setup in RTEMS driver definition

Background
I am using RTEMS and trying to set up a native NFS client. Although i have included this correctly there are not enough dynamic driver entries available for the Driver. You can seek more information here.
Implementation
In order to set up the extra dynamic drivers one needs to add NULL elements to a large table of free drivers. See the following:
#define NULL_DRIVER_TABLE_ENTRY \
{ NULL, NULL, NULL, NULL, NULL, NULL}
#ifdef CONFIGURE_INIT
rtems_driver_address_table Device_drivers[] = {
#ifdef CONFIGURE_BSP_PREREQUISITE_DRIVERS
CONFIGURE_BSP_PREREQUISITE_DRIVERS,
#endif
#ifdef CONFIGURE_APPLICATION_PREREQUISITE_DRIVERS
CONFIGURE_APPLICATION_PREREQUISITE_DRIVERS,
#endif
...
#ifdef CONFIGURE_APPLICATION_EXTRA_DRIVERS
CONFIGURE_APPLICATION_EXTRA_DRIVERS,
#endif
#ifdef CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER
NULL_DRIVER_TABLE_ENTRY
#elif !defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \
!defined(CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER) && \
!defined(CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER) && \
!defined(CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER) && \
!defined(CONFIGURE_APPLICATION_NEEDS_IDE_DRIVER) && \
!defined(CONFIGURE_APPLICATION_NEEDS_ATA_DRIVER) && \
!defined(CONFIGURE_APPLICATION_EXTRA_DRIVERS)
NULL_DRIVER_TABLE_ENTRY
#endif
};
#endif
Essentially what this is doing is building the device driver table ...
A deice driver looks like this:
typedef struct {
rtems_device_driver_entry initialization_entry; /* initialization procedure */
rtems_device_driver_entry open_entry; /* open request procedure */
rtems_device_driver_entry close_entry; /* close request procedure */
rtems_device_driver_entry read_entry; /* read request procedure */
rtems_device_driver_entry write_entry; /* write request procedure */
rtems_device_driver_entry control_entry; /* special functions procedure */
} rtems_driver_address_table;
Problem
The problem which may be exceptionally simple is that when i build this i get the following error:
confdefs.h:568: error: too many initializers for 'rtems_driver_address_table'
From looking here this appears to be a problem compiling with an unspecified number of table elements. What I don't understand is that this is currently working in that if I specify the NULL_DRIVER_TABLE_ENTRY with 7 NULLs (the number i need), it will fail, but with 6 NULLs it works perfectly fine?
As far as i can tell there is no definition as to the size of this table or its elements? Any ideas?
So this was a silly mistake...
The way this table works is that the NULL table entry:
#define NULL_DRIVER_TABLE_ENTRY \
{ NULL, NULL, NULL, NULL, NULL, NULL}
Is actually an entry in the array which corresponds to an rtems_driver_address_table. This driver has 6 elements and i was trying to have 7. The solution to this was to add an extra null entry as follows:
rtems_driver_address_table Device_drivers[] = {
...
#ifdef CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER
NULL_DRIVER_TABLE_ENTRY,
NULL_DRIVER_TABLE_ENTRY // Add extra entry here!
...
};

C/C++ Bitwise OR and how to interpret it

I have absolutely no idea about bitwise OR stuff.
So here is my problem. I am using a library libsndfile. I use it to read an analyze audio files. I need to tell the bitrate of the audio file.
I read a 24 bit wav audio file in. The api provides a field format, which is set to format = 65539.
The documentation tells me this:
The format field in the above SF_INFO structure is made up of the bit-wise OR of a major format type (values between 0x10000 and 0x08000000), a minor format type (with values less than 0x10000) and an optional endian-ness value.
Here are some possible values:
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
SF_FORMAT_VOC = 0x080000, /* VOC files. */
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
SF_FORMAT_WVE = 0x190000, /* Psion WVE format */
SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */
SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */
SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */
/* Subtypes from here on. */
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
My big question is: How can I analyze the format = 65539 to tell the major type and subtype ?
thanks so much in advance.
Just plug it into your calculator on your desktop and convert to hex:
65539 == 0x010003
Which is to say:
65539 == (0x010000) | (0x3)
which looks like SF_FORMAT_WAV | SF_FORMAT_PCM_24.
You need to determine the bit ranges of the different pieces you're interested in. Looking at the list, there are 2 hex digits devoted to the major type and 4 digits to the subtype. Use AND (&) to break them apart.
major = type & 0xff0000;
subtype = type & 0x00ffff;

How to write Special characters in a file using mfc application?

I want to write special charaters like ô. ö‚`a¹½ˆ in a file. I am working in MFC and using UNICODE character set. While showing string in message box is working good but its not writing the characters to the file.
Here is parts of my code:
CString abc=_T("hello");
CString xyz=compress(abc); //compressing value and return special characters
CStdioFile file_object(_T("abc.txt"),CFile::modeCreate|CFile::modeWrite);
file_object.WriteString(xyz);
It seems that CStdioFile class does not support Unicode characters directly. You can use this workaround (from this CodeProject article)
// Open the file with the specified encoding
FILE *fStream;
errno_t e = _tfopen_s(&fStream, _T("abc.txt"), _T("wt,ccs=UTF-8"));
if (e != 0) return; // failed..
CStdioFile f(fStream); // open the file from this stream
f.WriteString(xyz);
f.Close();
//
// For Reading
//
// Open the file with the specified encoding
FILE *fStream;
errno_t e = _tfopen_s(&fStream, _T("abc.txt"), _T("rt,ccs=UTF-8"));
if (e != 0) return; // failed..CString sRead;
CStdioFile f(fStream); // open the file from this stream
CString sRead;
f.ReadString(sRead);
f.Close();
Instead of using "UTF-8" encoding, you can also use the following encodings:
“ccs=UNICODE” => UTF-16 (Big endian)
“ccs=UTF-8” => UTF-8
“ccs=UTF-16LE” => UTFS-16LE (Little endian)
“ccs=ANSI” => ANSI (default encoding of the OS)
I found one more method. It is working good...
CString text=_T("HelloÄ^°H©º+");
CString strFilePath=_T("C:\\try.txt");
CFile theFile(strFilePath, CFile::modeReadWrite | CFile::modeCreate);
theFile.Write( (LPCTSTR) text, text.GetLength() * sizeof(TCHAR));
theFile.Close();