Totally IMHO and my 2¢ only... I probably wouldn't bother forking this stuff just for the change I proposed. It's a small module and not very well-written either. It shouldn't be too hard to "fork" it and then to re-write it properly, into a better module. For instance a module that is parametrised instead of hard-coding accesses to the global ParamStr(). Or that has a more robust way of constructing the data string that gets sent to the first instance. I haven't looked into the nitty-gritty of the code, just the actual sending of the parameters, but it doesn't seem to be rocket science
I have done IPC before so I might look into this and come back with some ideas.
And in everyday use of Cud I know how to deal with this problem now so it's NBD.
Loading files when ui_one_instance is true
https://forum.lazarus.freepascal.org/in ... #msg365298
I can add this event (if autor sleeps) and will fix it
I can add this event (if autor sleeps) and will fix it
Funny... I have this morning started to think about this and had written a short note. I honestly think it would be better (in the long run) to fork this TUniqueInstance stuff and do the changes locally. As a matter of fact, I would do it myself if knew Lazarus/Free Pascal. I could certainly try to do a first approximation but as I can't compile and test it it would certainly not work OOTB.
Anyway, here are my ideas:
Anyway, here are my ideas:
I have three suggestions if you ever decide to fork (or rewrite) the TUniqueInstance stuff.
1. Change the code within GetFormattedParams() (uniqueinstancebase.pas, line 39) so that it accepts an array of strings with the command-line parameters (CLParray) instead of using hardcoded accesses to ParamStrUTF8(). This requires a change to TUniqueInstance.Loaded() (uniqueinstance.pas, line 119) because this is the main interface, so you would have the CLParray as an argument to TUniqueInstance.Loaded() which in turn gives them to GetFormattedParams().
This change would allow to add to or change the CLParray as required before it gets transmitted to the the first instance.
2. Change the ParamsSeparator (line 11, uniqueinstancebase.pas) from '|' to something more sensible. A good candidate might be \x00 but I don't know whether binary zeroes are legal in Pascal strings. Another choice could be '\n' or another control character between \x01 to \x1f.
3. Enable communication between **separate** first instances and their respective **second** instances. This is a slightly tricky concept but it would enable nifty stuff like the following:
3.1. Start a cudatext first instance with an id of "cudatext.1" by running "cudatext -id=cudatext.1 file1a.txt".
3.2. Start another cudatext first instance with an id of "cudatext.2" by running "cudatext -id=cudatext.2 file2a.txt".
3.3. Add a file to the running cudatext.1 instance by running "cudatext -id=cudatext.1 file1b.txt".
3.4. Add a file to the running cudatext.2 instance by running "cudatext -id=cudatext.2 file2b.txt".
Admittedly, this is something for command-line freaks and power-users (I have patched all open-source editors I've used so that they supported this sort of thing but I don't think I will for Cud because I have absolutely no idea about Lazarus development ).
For this Cud would need an -id=... command line argument and then this id has to be set before calling TUniqueInstance.Loaded(). There's a line (757) in formmain.lfm that probably sets this id to a fixed "cudatext.0"; I don't know enough about the inner workings of FP/Lazarus to say what and where you have to change stuff to set this dynamically but I'm sure you know:-)
no need in that. yet.... so I forked that code. renamed to AppUniqueInstance. and changed Loaded to Loaded(array of string).
and passed good array in it.
seems now it works! beta- http://uvviewsoft.com/c/
good.
and passed good array in it.
seems now it works! beta- http://uvviewsoft.com/c/
good.
I will look into the version you uploaded and report back, though it may take a while as I am currently under Windows to do some maintenance.
In general... it is IMHO almost always an error for developers to assume they know what is best for their users or what will be used (and how it will be used) or won't be used. This brings us software like MS Windows or the GTK stuff. Secondly, I don't think that this issue does need an immediate resolution. I'd rather have something that is well designed and well-thought through than a quick fix.
As to the IPC bit itself... a first instance registers itself as the first instance by creating an IPC server using a unique id string (Cud uses the hardcoded 'cudatext.0' as a unique id) and waiting for second instances to query that unique id. In other words, the definition of a first instance is exactly that it uses an id string that has as yet not been registered by another instance.
Any freshly started instance looks for a previous instance with their own id string and if they can't find a running IPC server instance with this id string then they are the first instance. If they can find it, they have found their corresponding first instance and simply send their data over to their first instance.
Going back to my earlier example:
1. Start a cudatext first instance with an id of "cudatext.1" by running "cudatext -id=cudatext.1 file1a.txt". This registers an IPC server with id 'cudatext.1' which waits for second instances.
2. Start another cudatext first instance with an id of "cudatext.2" by running "cudatext -id=cudatext.2 file2a.txt". This registers another IPC server with id 'cudatext.2' which waits for second instances.
3. Start a third cudatext instance by running "cudatext -id=cudatext.1 file1b.txt". This instance looks for an IPC server with id 'cudatext.1', finds it and sends its parameters over. The first instance receives those parameters and does its job. The third instance terminates.
4. Start another third cudatext instance by running "cudatext -id=cudatext.2 file2b.txt". This instance looks for an IPC server with id 'cudatext.2', finds it and sends its parameters over. The first instance receives those parameters and does its job. The third instance terminates.
Pseudo code (based on your changed formmain.pas, see procedure InitUniqueInstanceObject):
uniqIdString=GetIdstringFromParamStrArray(...); // get unique idstring from -id=blabla command line option
AppUniqInst.Identifier:= uniqIdString;
Try it... either it works or it doesn't . Whatever it does, I don't think your PC will go up in flames
And I do appreciate that you're looking into this
Well, I for one need it: as I wrote, I have patched every single editor (if I had the source code in a language I could readily work with ) to implement exactly this feature.Alexey wrote:>Enable communication between **separate** first instances and their respective **second** instances. This is a slightly tricky concept
hmm, I don't like that idea- I dont know IPC codde at all (I just use ready wrapper) and it sounds tricky. noone will need it..
In general... it is IMHO almost always an error for developers to assume they know what is best for their users or what will be used (and how it will be used) or won't be used. This brings us software like MS Windows or the GTK stuff. Secondly, I don't think that this issue does need an immediate resolution. I'd rather have something that is well designed and well-thought through than a quick fix.
As to the IPC bit itself... a first instance registers itself as the first instance by creating an IPC server using a unique id string (Cud uses the hardcoded 'cudatext.0' as a unique id) and waiting for second instances to query that unique id. In other words, the definition of a first instance is exactly that it uses an id string that has as yet not been registered by another instance.
Any freshly started instance looks for a previous instance with their own id string and if they can't find a running IPC server instance with this id string then they are the first instance. If they can find it, they have found their corresponding first instance and simply send their data over to their first instance.
Going back to my earlier example:
1. Start a cudatext first instance with an id of "cudatext.1" by running "cudatext -id=cudatext.1 file1a.txt". This registers an IPC server with id 'cudatext.1' which waits for second instances.
2. Start another cudatext first instance with an id of "cudatext.2" by running "cudatext -id=cudatext.2 file2a.txt". This registers another IPC server with id 'cudatext.2' which waits for second instances.
3. Start a third cudatext instance by running "cudatext -id=cudatext.1 file1b.txt". This instance looks for an IPC server with id 'cudatext.1', finds it and sends its parameters over. The first instance receives those parameters and does its job. The third instance terminates.
4. Start another third cudatext instance by running "cudatext -id=cudatext.2 file2b.txt". This instance looks for an IPC server with id 'cudatext.2', finds it and sends its parameters over. The first instance receives those parameters and does its job. The third instance terminates.
Pseudo code (based on your changed formmain.pas, see procedure InitUniqueInstanceObject):
uniqIdString=GetIdstringFromParamStrArray(...); // get unique idstring from -id=blabla command line option
AppUniqInst.Identifier:= uniqIdString;
Try it... either it works or it doesn't . Whatever it does, I don't think your PC will go up in flames
And I do appreciate that you're looking into this
done as suggested. tested on Linux, -id=name works Ok.
http://uvviewsoft.com/c/
http://uvviewsoft.com/c/