How to detect when text is replaced in GtkTextBuffer instead of delete followed by insert? - c

I have worked a great deal with the text system in Objective-C for macOS/iOS (e.g. NSTextView, NSTextStorage, etc.) I am now experimenting with GTK3 to see how well I can translate my project for use on Linux, etc.
I am brand new to using GTK, but after a few days of Google time and experimenting, I have a working text editor prototype with my custom code plugged in.
The problem is this -- I need to be able to detect when a user highlights a section of text, and then replaces it with other text (e.g. a keystroke). This is distinct from highlighting a section of text, hitting the delete key, and then typing the new text. A specific use example would be highlighting a word, then typing a double quote character in order to wrap the word in quotes (e.g. foo becomes "foo").
In Cocoa, one would receive replaceCharactersInRange: that indicates the range originally selected, as well as the new string to replace it with. I can then detect the presumed intent of the user based on the information received.
In GTK, it seems that we receive a delete-range signal, followed by a separate insert-text signal. Because of this separation, the code in the "insert" section has no way of knowing that the user intended to replace text, not insert new text.
I used the following to receive the signals above:
g_signal_connect(buffer, "insert-text", G_CALLBACK(insert_text_cb), NULL);
g_signal_connect(buffer, "delete-range", G_CALLBACK(delete_range_cb), NULL);
Is there something else I can do in order to tell that there is a delete, followed by an insert as part of the same user action?
Thanks for any pointers offered!

Instead of trying to correlate the delete and insert events, I would suggest creating a GAction for your desired action (e.g. toggle quotes around the selected text) and setting its shortcut key to " using gtk_application_set_accels_for_action().
For more information, check out this HowDoI wiki page.

No answers over the last month, so I kept brainstorming and digging around. I finally came up with this, which works, but is not quite as elegant as I had hoped.
Handle delete-range signal as before, but keep track of the the deleted text for later (e.g. in char * deletedText).
Handle the insert-text signal as before, but if we have a string in deletedText then change the behavior to perform a replacement instead of an insertion. In my case, this actually meant inserting the deleted text back in, and then performing the replacement.
Add a callback for the end-user-action signal, which indicates that all delete/inserts associated with a particular action are complete. In this callback, free deletedText from above and set to NULL (to indicate that everything has been handled).
Again -- this works, but feels a bit inelegant. And depending on how complex your delete/insert routines are, it may slow the performance slightly since some steps have to be duplicated. A better solution would be to detect during the delete-range callback that there is a pending insert-text callback and handle both steps at once. I have thus far not been able to do that.

Related

LabVIEW: Count how long a button has been pressed

I'm trying to create a LabVIEW VI with an "ok button", a numeric indicator "Number of click" and an array of cluster, in which every cluster contain a TimeStamp indicator and a numeric indicator.
When the VI is running I want to keep track of:
When the button is released (timestamp)
How long the button has been pressed (in millisecond or second).
Then, when i click on STOP, i want to visualize these information about ALL the button pression in the array of cluster.
That's what I've done. I've tried to change the manner in which I create the array, and also the "Tunnel mode" in the While loop, but it doesn't work..
Can you help me? Thank you all!
please check my attached code and compare it with yours.
It's the simplest method, but you may also read about Event Structure, which would help to do that in much smarter way. Additionally you may want to change my code a bit to have indicators being updated in real-time instead after the exit. It's worth also reading about "Feedback node" and "Conditional" type of output tunnels. They would help to simplify the code, but I didn't use them to keep it as simple as possible!

How to Cancel/Reset page between StartPage/EndPage when printing?

I'm processing a specially formatted text file to send to the printer. I have encountered a condition that would be easiest to handle by discarding the current (incomplete) page and starting a new one instead. So, I have called StartPage() and output one or more lines of output and then I realize that I need to discard what I have output on this page only before I have called EndPage(). To me, this seems like it should be a simple and obvious function, but I have been unable to find any way to do this. Is it possible or am I just dreaming?
EDIT: In case this wasn't clear, I want to remove a single, partially completed page from my output and then continue to output additional pages. I DO NOT want to remove the entire job (or print queue.)
It appears that what I want does not exist.
I have assumed that between StartPage() and EndPage(), my printer output for the page is being buffered to build an image of the page to send to the printer. Apparently I can neither (a) change my mind and discard the incomplete (or completed) page nor (b) change (or remove) what I have already written to the page. I tried (b) and I got two lines of text superimposed upon one another.

Get a list of dead keys in X11

Is there a way to check for dead keys in the current layout? I am currently capturing the users input for a project I am doing. I created a map of all keys on the keyboard, but there seems to be no flag or whatsoever defining a key as dead or not. I use libxkb in my current code.
The layout is retrieved using
KeySym * keysyms = XGetKeyboardMapping(display_, keycode_low, keycode_high - keycode_low + 1, &num_keysym);
I understand you need to know which key will not directly produce a character, maybe because you are writing a game and do not want to have it use keys as input that would require another key to be pressed to produce some output (if so, please mention in the question)
Not through standard Xlib calls, to my knowledge, and definitely not without actually pressing the respective key. Composing is entirely done within Xlib, and transparent to the front end. (For its original purpose, it should be as transparent as possible to work properly, after all)
You could, however, do the same thing that Xlib does and parse through the various Compose configuration files starting with $HOME/.Xcompose. But that could be a tedious process.
On second thought, I am definitely not proposing the following:
You could, for each key you are looking for information, create a synthetic keypress event and feed it into XLookupString. Hand in an emptied XComposeStatus structure as well. If the structure returns modified, this could be a strong hint you have found a compose key. But it could also mean the server modifies it without any need..... If I were very desparate, I'd probably try.

GLUT doesn't detect properly more then 2 keys pressed?

I'm trying to make a small game using (free)GLUT. I know that it's old and there are better alternatives, but currently I prefer to stick with it and use it as much as possible. I program with C.
I'm currently trying to make GLUT detect properly all the keys I press.
I use glutKeyboardFunc, glutKeyboardUpFunc, glutSpecialFunc and glutSpecialUpFunc to detect pressed keys and I store their state in a short array I created (I currently have only 5 usable keys, so I just created a specific array for them).
However, while everything works fine for 2 keys or less, the game doesn't detect properly 3 keys or more. While for some keys it detect the combination properly (that actually happens for only 1 specific combination), for others the functions simply don't detect the third key that I press.
I checked my code a few times, and there is nothing special about the combination that does work.
I also made glutKeyboardFunc and glutSpecialFunc directly print every key-press that they receive, and it seems they simply stop working after I press more then 2 keys.
Is it a known issue with GLUT or something? I googled a lot and didn't find anyone with a similar issue.
I am not very into GLUT but as I know, but you should make sure, that your keyboard supports more than 2 input keys at once. This feature is called n-key rollover. This page says, that 2-key rollover may be a common value for some keyboards, but you dont need to trust this source.
I'll clarify a point: The glutKeyBoardFunc is a callback i.e., it is invoked for every key pressed and re-executed over and over again and all the if-else (or switch-case) statements for various key combinations are executed. What it means is this - if you were to press 'A', '->' (right arrow) and 'D' all at once, depending on which key-press event was received first the callback will be executed accordingly. Sometimes with a delay and sometimes the on screen animation may stop momentarily.
GLUT is purely for educational/learning purposes but not good for full blown applications since that's not what it was designed for. You land up using OS specific libs or other languages (e.g., Qt) to embed OpenGL "window" within them and execute the keyboard events etc., The event handling in those (and/or OS specific frameworks) is radically different (and better) than GLUT.
You may want to keep your simultaneous key presses to a minimum. You may augment it with the mouse to get rid of the jerky response/processing...

MPQueue - what is it and how do I use it?

I encountered a bug that has me beat. Fortunately, I found a work around here (not necessary reading to answer this q) -
http://lists.apple.com/archives/quartz-dev/2009/Oct/msg00088.html
The problem is, I don't understand all of it. I am ok with the event taps etc, but I am supposed to 'set up a thread-safe queue) using MPQueue, add events to it pull them back off later.
Can anyone tell me what an MPQueue is, and how I create one - also how to add items and read/remove items? Google hasn't helped at all.
It's one of the Multiprocessing Services APIs.
… [A] message queue… can be used to notify (that is, send) and wait for (that is, receive) messages consisting of three pointer-sized values in a preemptively safe manner.

Resources