Hi,
I would like to get the list of all available characters from the keyboard (Digital Alphabetical) in order to create a NSArray.
TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
NSLog(#"languages: %#", TISGetInputSourceProperty(source, kTISPropertyInputSourceLanguages));
NSLog(#"localized name: %#", TISGetInputSourceProperty(source, kTISPropertyLocalizedName));
I use these lines, but I can't find the right function to list the characters.
I also tried this line :
NSLog(#"List: %#", TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData));
Would you be able to get it from calling:
TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
That will return the 'uchr' data for the keyboard layout (if it exists), as a CFDataRef. You can read about the layout of the 'uchr' data here. You'll need to get the bytes from the CFDataRef, probably by calling something like CFDataGetBytes() or CFDataGetBytePtr().
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
Byte* buffer =
(Byte*) malloc (sizeof(Byte) * CFDataGetLength(uchr));
CFDataGetBytes(
uchr,
CFRangeMake(0,CFDataGetLength(uchr)),
buffer
);
How to read the information contained in the CFDataRef ?
Related
need to use IOServiceAddMatchingNotification routine for supporing multiple product identifications.
To show the concept, I got part of this code from a site and revised it.Kept it short.
// Set up matching dictionary.
NSMutableDictionary* matchingDictionary;
for (int n = 0; n < numberOfDevices; n++)
{
matchingDictionary = (NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName);
[matchingDictionary setObject:[NSNumber numberWithLong:myVid[n]] forKey:[NSString stringWithUTF8String:kUSBVendorID]];
[matchingDictionary setObject:[NSNumber numberWithLong:myPid[n]] forKey:[NSString stringWithUTF8String:kUSBProductID]];
// Set up a notification callback for device addition on first match.
IOServiceAddMatchingNotification(g_notificationPort, kIOFirstMatchNotification, (CFMutableDictionaryRef)matchingDictionary, deviceAddedCallback, (void*)self, &g_iteratorAdded);
}
I am not sure if it really is correct?. I did not see complains from the xcode and it works.
This requires a nuanced answer - there are three things to note here:
In principle, yes, you need to create distinct matching notifications for each independent match dictionary.
However, it looks like you're expecting only one io_iterator_t to be created and updated with each matching dictionary, as you only have a single variable to store it, g_iteratorAdded. This is not the case. The code shown suffers from a resource leak. Each successful call to IOServiceAddMatchingNotification will create a new iterator, so you will need to retain all of them in an array or so. And then, when you no longer need the notifications (at the latest, when self is dealloc'd, or you'll get callbacks on a freed object!), you need to release all of the iterators.
For matching multiple different USB product IDs but identical vendor IDs, you actually don't need to create multiple match dictionaries and notifications. Instead of kUSBProductID with a single NSNumber/CFNumber, provide a kUSBProductIdsArrayName (aka kUSBHostMatchingPropertyProductIDArray) and specify an array of numbers. (NSArray/CFArray containing a NSNumber/CFNumber for every product ID.)Alternatively, if your product IDs match some hex pattern, you can also use kUSBProductIDMask in conjunction with kUSBProductID: in this case, candidate devices' product IDs will be bitwise masked (&) with the number provided for kUSBProductIDMask before comparing to the kUSBProductID.
If you need to match multiple vendor IDs, you will still need to create a matching notification for each vendor ID, and provide the list of product IDs in the kUSBProductIdsArrayName value for each.
Update: Sample code for array PID match dictionaries
Some rough untested code for dealing with kUSBProductIdsArrayName, assuming your VIDs/PIDs are laid out like this:
static const uint16_t myVid[] = { 0x1234, 0x5555 };
static const size_t numberOfVids = sizeof(myVid) / sizeof(myVid[0]);
static const uint16_t myPid[] = {
// for VID 0x1234
0x1, 0x2, 0x3, 0x1001, 0x1002,
// for VID 0x555
0x100, 0x101,
};
static const unsigned pidsForVid[] = { 5, 2 };
Setting up the matching dictionaries would then look something like this:
unsigned next_pid_index = 0;
for (int n = 0; n < numberOfVids; n++)
{
NSMutableDictionary* matchingDictionary =
(__bridge_transfer NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName);
[matchingDictionary setObject:#(myVid[n]) forKey:#kUSBVendorID];
NSMutableArray* pid_array = [NSMutableArray arrayWithCapacity:pidsForVid[n]];
for (unsigned i = 0; i < pidsForVid[n]; ++i)
{
[pid_array addObject:#(myPid[next_pid_index])];
++next_pid_index;
}
[matchingDictionary setObject:pid_array forKey:#kUSBProductIdsArrayName];
// Set up a notification callback for device addition on first match.
IOReturn result = IOServiceAddMatchingNotification(
g_notificationPort,
kIOFirstMatchNotification,
(__bridge_retained CFMutableDictionaryRef)matchingDictionary,
deviceAddedCallback,
(__bridge void*)self,
&g_iteratorAdded[n]);
assert(result == kIOReturnSuccess);
}
i am using Cocoa with Accessibility API system wide to obtain some info like text value, selected text value but is there a way to change any of that? As you can see on my picture, you can edit the location of the keyboard cursor (Loc) and the length (Len) of the selected text so there must be a way to do this programmatically. Also, I am looking how to get the keyboard cursor position (blinking caret) inside the screen even if nothing is selected. (I have seen applications doing it)
EDIT :
This is my code so far to get the attribute :
AXValueRef textValue = NULL;
//Get the location string inside the selectedtextrange
AXError gettextvalueError = AXUIElementCopyAttributeValue(focussedElement, kAXSelectedTextRangeAttribute , (CFTypeRef *)&textValue); //get the text value of focussedElement in object textValue
if(gettextvalueError != kAXErrorSuccess){
NSLog(#"error");
}else{
NSString* textStr = (__bridge NSString*)textValue; // Convert textValue to NSString
}
This is getting me a string containing bounds object of the selected text and location + length. Is it possible to only change the location.
<AXValue 0x7f8dda3c4340> {value = location:3 length:0 type = kAXValueCFRangeType}
First, the value you get is not a string object. Casting it to NSString* doesn't "convert" it, it just lies to the compiler. The reason that logging it works is that %# asks the object for its description and the AXValue object describes itself as you're seeing in the output.
To decode the value, use code like this:
CFRange range;
if (AXValueGetValue(textValue, kAXValueTypeCFRange, &range))
{
// use the range
}
else
/* the value isn't of the type that the attribute is supposed to have; abort */;
If you want to change it:
range.location = /* some new value */;
AXValueRef newValue = AXValueCreate(kAXValueTypeCFRange, &range);
if (newValue)
{
AXError setError = AXUIElementSetAttributeValue(focussedElement, kAXSelectedTextRangeAttribute, newValue);
/* check setError and handle as appropriate */
CFRelease(newValue);
}
else
/* handle failure */;
I m trying to change color space for image objects of a pdf file, but first problem is that I cannot find ICC color profile inside pdf metadata.
All I have in Metadata is one array with 2 components:
ColorSpace :
Name value: ICCBased
Stream value (null)
And when I get the Stream parsed into a dictionary:
Color Space Name ICCBased
Filter :
Name value: FlateDecode
Length :
integer value: 389757
N :
integer value: 4
Range :
ARRAY with value:
integer value: 0
integer value: 1
integer value: 0
integer value: 1
integer value: 0
integer value: 1
integer value: 0
integer value: 1
But I am unable to find in metadata the ICC profile data used on the color space of the image, the one you can see with acrobat:
By the way, if you are interested on how to get metadata form pdf file with coreGraphics here I put some code:
...
CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL(pdfURL);
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, pageNumber);
CGPDFContentStreamRef contentStream =
CGPDFContentStreamCreateWithPage(page); CGPDFOperatorTableRef
operatorTable = CGPDFOperatorTableCreate();
CGPDFOperatorTableSetCallback(operatorTable, "Do", &op_Do);
CGPDFScannerRef contentStreamScanner =
CGPDFScannerCreate(contentStream, operatorTable, NULL);
CGPDFScannerScan(contentStreamScanner);
....
And then on the callback:
static void op_Do(CGPDFScannerRef s, void *info) {
CGPDFObjectRef imageObject = CGPDFContentStreamGetResource(cs, "XObject", imageLabel);
CGPDFStreamRef xObjectStream;
if (CGPDFObjectGetValue(imageObject, kCGPDFObjectTypeStream, &xObjectStream)) {
CGPDFDictionaryRef xObjectDictionary = CGPDFStreamGetDictionary(xObjectStream);
const char *subtype;
CGPDFDictionaryGetName(xObjectDictionary, "Subtype", &subtype);
if (strcmp(subtype, "Image") == 0) {
NSString *imageID = [NSString stringWithCString: imageLabel encoding: NSASCIIStringEncoding];
CGPDFDictionaryApplyFunction(xObjectDictionary, ListDictionaryObjects, NULL);
if (CGPDFDictionaryGetName(xObjectDictionary, "ColorSpace", &colorSpaceName)){
fprintf(stdout,"Color Space Name %s\n", colorSpaceName);
}else{
//Getting Color space array
CGPDFArrayRef objectArray;
CGPDFDictionaryGetArray(xObjectDictionary, "ColorSpace", &objectArray);
//getting each array position
CGPDFStreamRef colorsSpaceStream;
CGPDFArrayGetName(objectArray, 0, &colorSpaceName);
fprintf(stdout,"Color Space Name %s\n", colorSpaceName);
CGPDFArrayGetStream(objectArray, 1, &colorsSpaceStream);
CGPDFDictionaryRef dictionary = CGPDFStreamGetDictionary(colorsSpaceStream);
CGPDFDictionaryApplyFunction(dictionary, ListDictionaryObjectsLow, NULL);
}
...
And finally in ListDictionaryObjects functions I go through dictionary objects:
void ListDictionaryObjects (const char *key, CGPDFObjectRef object, void *info) {
fprintf(stdout, "%s :\n", key);
CGPDFObjectType type = CGPDFObjectGetType(object);
switch (type) {
case kCGPDFObjectTypeDictionary: {
CGPDFDictionaryRef objectDictionary;
if (CGPDFObjectGetValue(object, kCGPDFObjectTypeDictionary, &objectDictionary)) {
fprintf(stdout," Dictionary value with: %zd elements\n", CGPDFDictionaryGetCount(objectDictionary));
CGPDFDictionaryApplyFunction(objectDictionary, ListDictionaryObjectsLow, NULL);
}
}
break;
case kCGPDFObjectTypeInteger: {
CGPDFInteger objectInteger;
if (CGPDFObjectGetValue(object, kCGPDFObjectTypeInteger, &objectInteger)) {
fprintf(stdout," integer value: %ld \n", (long int)objectInteger);
}
}
break;
case kCGPDFObjectTypeReal:{
CGPDFReal objectReal;
if (CGPDFObjectGetValue(object, kCGPDFObjectTypeReal, &objectReal)){
fprintf(stdout," real value: %5.2f\n", objectReal);
}
} ...
Assigning a new color profile (i.e. without altering values in the object) to all objects of a certain color space can be done by creating a Quartz Filter with ColorSync Utility.
A technical note from the Mac Developer Library from 2005 about "ColorSync on Mac OS X" stated:
Quartz filters are currently available only through the various Mac OS X system-built utilities and applications. However, a new set of API's will be forthcoming.
But I could not find any other mention to Quartz Filters in Apple's documentation for developers.
I know this is not terribly helpful, but maybe it gives you a hint of were to look.
Edit: See this answer to "Apply a Quartz filter while saving PDF under Mac OS X 10.6.3"
What you're seeing is described in the PDF specification:
http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
Look for section 8.6.5.5 which defines ICC-based color spaces - the data that you are looking for is contained in the stream you paste at the top of your message. It's not readily recognisable because it has been Flate encoded (ZIP encoded).
The question is what exactly you want to accomplish? If you just want to throw away this ICC based color space and create a new one, you don't need to find this data, just create a new color space object and make the image refer to your new object.
To change the existing ICC profile (which would be a bad idea in general), you'd have to decompress the stream data, adjust what you want to adjust and recompress it again.
These are followed steps:
1- Create your Quartz filter with ColorSync utility and save it as .qfilter file
2- apply this filter to your pdf file with this code:
PDFDocument *pdf = [[PDFDocument alloc]initWithURL:[NSURL fileURLWithPath:#"_pdfURL_"]];
NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:[QuartzFilter quartzFilterWithURL:[NSURL fileURLWithPath:#"_myFilter.qfilter_"]], #"QuartzFilter", nil];
[pdf writeToFile:#"_pdfFilePath_" withOptions:dict];
I'm new to Objective-C, and this is really my first program that is interactive. I've been learning for about 2 weeks now.
So, my question is: typically I've noticed when you have multiple scanf's in a row, they each wait for input - however in this situation, where I ask for account owner name, and balance - it fires both NSLog functions instead of waiting for the first input.
Here is my main:
int main(int argc, char* argV[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
bank *columbiaBank = [[bank alloc] init];
int iteration = 0;
while (true) {
int selection = 0;
NSLog(#"\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?:");
scanf("%i", &selection);
if (selection == 1) {
NSLog(#"\nEnter account owner:");
char accountOwner;
scanf("%c", &accountOwner);
NSLog(#"\nEnter opening balance:");
float openingBalance;
scanf("%f", &openingBalance);
// create and add new account
bankAccount *newAccount = [[bankAccount alloc] initWithProps:[NSString stringWithFormat:#"%c", accountOwner] :[NSString stringWithFormat:#"%i", iteration] :openingBalance];
[columbiaBank addAccount:newAccount];
[newAccount release];
NSLog(#"\nAccount successfully added!");
} else if (selection == 2) {
NSLog(#"\nEnter account id:");
int accountId;
scanf("%i", &accountId);
// remove account
[columbiaBank removeAccount:[NSString stringWithFormat:#"%i", accountId]];
NSLog(#"\nAccount successfully removed!");
} else if (selection == 3) {
NSLog(#"\nThe bank currently has %i accounts.", columbiaBank.totalAccounts);
NSLog(#"\nThe bank's current balance from all accounts is $%f", columbiaBank.totalBankBalance);
NSLog(#"\n-- Output of all account info --");
[columbiaBank printAccounts];
} else {
NSLog(#"You did not enter a valid action.");
}
iteration++;
}
[columbiaBank release];
[pool drain];
return false;
}
Other users already said everything about it. The scanf inserts a new line "\n" automatically in the buffer that is passed to the next scanf. This is because any unwritten data is written in the next stream.
I want to add that you can use fflush to clear the stream buffer, in this case you want to use
scanf("%i", &selection);
fflush(stdin)
to clear the buffer of stdin (the console input) after every scanf.
Edit: I didn't know that, but As #Peter Kowalski said the use of fflush(stdin), for input stream, should be avoided because it has an undefined behaviour for input streams.
Cprograming.com FAQ > Why fflush(stdin) is wrong.
But it seems that there is not a guaranteed method to flush the input stream in C.
Cprograming.com FAQ > Flush the input stream
I know that in C++ a standard way is to use cin.ignore() after cin >> selection but I don't know how this can be done in C. Maybe some more experienced user can give some insight on what is happening with fflush(stdin).
*[Note: If you are going to use Objective-C you might wish to use input conversion methods from Cocoa rather than mix Cocoa (NSLog) and stdio (scanf). But that doesn't answer your question...]
When parsing integers, floats and even strings scanf skips whitespace - e.g. spaces, tabs, end of line, etc. - and every input line ends with at least an end of line (which may be a carriage return, line feed, or both depending on the system). This means that after reading your first integer there is still, at least, an end of line in the input and the attempt to read a character will return it - hence no wait for input. To discard the remaining, unused, input you can use fpurge. E.g.:
#include <stdio.h>
int main(int argc, char* argV[])
{
int selection = 0;
fputs("\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?: ", stdout);
scanf("%i", &selection);
if (selection == 1)
{
fputs("\nEnter account owner: ", stdout);
fpurge(stdin); // skip any input left in the buffer as %c takes the very next character and does not skip whitespace
char accountOwner;
scanf("%c", &accountOwner);
fputs("\nEnter opening balance: ", stdout);
float openingBalance;
scanf("%f", &openingBalance);
printf("%c - %f\n", accountOwner, openingBalance);
}
}
Note that reading in character strings does skip whitespace, so if your account owner was a string you would not need the fpurge.
Presumably you want the account owner name to be more than a single character, but you're only reading a single character in that scanf. If you're trying to enter more than a single character there, the first scanf will read the first character, and since there's more in the input buffer, the next scanf will try to read immediately without waiting for your numeric input. If you are only using a single character for the owner name, then you'll need to consume the newline from the input buffer.
If you want to read a string as the account owner name, you'll need to allocate space for more than one character, and use %s rather than %c as your scanf format string. Also remember to check the return value for scanf. The function will return the number of items successfully scanned, or 0 if no items were scanned, typically due to invalid input, or return EOF.
char accountOwner[26];
// ...
// note that you can specify a width (max length) for a string using scanf
scanfReturn = scanf("%25s", accountOwner);
I'm looking for an easy way to parse VCALENDAR data with objective-c. Specifically all I am concerned with is the FREEBUSY data (See below):
BEGIN:VCALENDAR
VERSION:2.0
METHOD:REPLY
PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
BEGIN:VFREEBUSY
UID:XYZ-DONT-CARE
DTSTART:20090605T070000Z
DTEND:20090606T070000Z
ATTENDEE:/principals/__uids__/ABC1234-53D8-4079-8392-01274F97F5E1/
DTSTAMP:20090605T075430Z
FREEBUSY;FBTYPE=BUSY:20090605T170000Z/20090605T200000Z,20090605T223000Z/20
090606T003000Z
FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20090605T070000Z/20090605T150000Z,2009060
6T010000Z/20090606T070000Z
ORGANIZER:/principals/__uids__/ABC1234-53D8-4079-8392-01274F97F5E1/
END:VFREEBUSY
END:VCALENDAR
I've tried parsing it by using componentsSeparatedByString:#"\n", but there is a \n in part of the FREEBUSY data, causing it to not parse correctly.
Is there something easy that I'm missing?
The \n in the middle of FREEBUSY data is a part of the iCalendar spec; according to RFC 2445, the newline followed by a space is the correct way to split long lines, so you'll probably see a lot of this in scanning FREEBUSY data.
As Nathan suggests, an NSScanner may be all you need if the data you're expecting will be reasonably consistent. There are a number of vagaries in iCalendar, though, so I often find myself using libical to parse ics info. An quick-and-dirty example of parsing this data using libical:
NSString *caldata = #"BEGIN:VCALENDAR\nVERS....etc";
icalcomponent *root = icalparser_parse_string([caldata cStringUsingEncoding:NSUTF8StringEncoding]);
if (root) {
icalcomponent *c = icalcomponent_get_first_component(root, ICAL_VFREEBUSY_COMPONENT);
while (c) {
icalproperty *p = icalcomponent_get_first_property(c, ICAL_FREEBUSY_PROPERTY);
while (p) {
icalvalue *v = icalproperty_get_value(p);
// This gives: 20090605T170000Z/20090605T200000Z
// (note that stringWithCString is deprecated)
NSLog(#"FREEBUSY Value: %#", [NSString stringWithCString:icalvalue_as_ical_string(v)]);
icalparameter *m = icalproperty_get_first_parameter(p, ICAL_FBTYPE_PARAMETER);
while (m) {
// This gives: FBTYPE=BUSY
NSLog(#"Parameter: %#", [NSString stringWithCString:icalparameter_as_ical_string(m)]);
m = icalproperty_get_next_parameter(p, ICAL_FBTYPE_PARAMETER);
}
p = icalcomponent_get_next_property(c, ICAL_FREEBUSY_PROPERTY);
}
c = icalcomponent_get_next_component(root, ICAL_VFREEBUSY_COMPONENT);
}
icalcomponent_free(root);
}
Documentation for libical is in the project download itself (see UsingLibical.txt). There's also this lovely tutorial on shipping libical in your application bundle.
Take a look at NSScanner.