 Yeah, so who here understood everything from Stefan Backman's talk? Because if you did, you're wrong here, because this is going to be a bit of an introductory talk. And there won't be anything complex or very deep into the core. It's just for someone who gets started from maybe an extension or as a user and wants to know how to find stuff in writer and in the core. So it's a bit about navigating this 10 million lines of code thing that we have there, which is why we have these two boats there. And for a start, I will do a quick race through uniconcepts again. I did that already once, but it's always helpful just to get an idea of how the stuff in scripting actually works. In UNO, you have interfaces, services, and implementations. And interfaces are the stuff that define what you can actually do with something. And usually, they are named comm-sun-star-something, and they start with an x. That's roughly how you can tell it's an interface. And then there are services which also start with comm-sun-star and they do not start with an x. And these services are essentially the stuff that says, OK, they are defined by implementing interfaces. So if you have a service, you know this service will implement these interfaces. And finally, you have an implementation. And an implementation can implement a certain service so that you know it implements also the interfaces for that. And that's like the real code inside LibreOffice that actually does stuff. To make that, again, a bit more visual, for example, you could have cargo storage, which is you can store something in it. And you can transport, which means you can transport something with it that would be two interfaces that define what a UNO object does. And then you could, for example, have a lorry service that implements both of these interfaces, which means you can store something in it and you can transport something with it. And that is still abstract. It's not a concrete implementation, but it's the definition of these interfaces. And then you have the actual implementation, which is one specific lorry, which has all very personality and bugs and whatever. And that is the real implementation. And that is actually the stuff that is inside the LibreOffice core. One thing that is new, like since 5.1, I think, we have that in, is reflection. Well, not this stuff. This is ancient. So interface is like whatever you have an UNO object, you are holding an interface to it. And this is usually the stuff that you, whatever you do scripting, you're holding an X interface of some kind. And most of them actually have an X service info, and you can actually ask them, hey, what are you? Get implementation name. And you can also ask which services are supported. And from that, you can actually find out what you can do with this specific thing. So there's since, this is the stuff that is new, since 5.1, I think. I implemented a service documenter, which is a single that you can use in scripts to ask a specific, whenever you have something, you know, you can ask it, what can I do with it? And it has a function like show the service docs, which shows the specific service, or the interface docs, which shows all the interfaces of this thing. And here's in StarBasic, for example, how you would do that. You can get the service documenter by, this is just a global singleton. And with it, you can then, whatever component you have, for example, this component, you can then say, show me the service doc. And it will open up your default browser with the documentation for this specific thing. So when it's easy if you have this component, because you roughly have the idea, OK, I have a writer document at this point. But if you're like 20 levels deep into, I get a paragraph, and then I took a text selection. And from that, I took again that. You might not be sure what exactly you're holding there. And with this, you can just, at Hawker Runtime, find out, oh, what can this thing that I have there do, and what is it actually? You can do the same with show interface docs, which is all the interfaces. But if you do that with a writer document, you have like 20 tabs open, because it's so many. So this is just repeating the stuff about the unit part. And now we are going to do the hard things, which is, in this case, naming things. Because when I showed you the slide about the unit part, that was only the first part. We have the interfaces, which are comm, son, star, x something. Then we have the services, which are comm, son, star, not x something. Then we have the unit wrappers, which are actually the stuff in the LibreOffice core, which implement a specific service. So if you have a comm, son, star, x text range or something, something is implementing this in C++. And that is the unit wrapper. And then you have the real core implementation, which is probably even older than the unit wrapper. Because, for example, a writer, the core is from the 1980s in the oldest cases or 1990s. And then you was plugged on top of that at some point. So there is, again, mostly two classes there. And I want to show you how you get, if you have your script, which is like the upper part of this, the first two, how you get to the lower part. And actually, if you have, if LibreOffice scripting doesn't behave like you expected to, how you can fix this stuff. So for this, I choose some nifty bright colors, which is at the bottom the interfaces and services, which is, again, UNO. And then unit wrappers, this is the interface to UNO inside LibreOffice. So blue is already inside LibreOffice and core implementation is the stuff that is the real engine of, for example, writer. And to show you how you get from the outside to the inside, I'm using the Python tests that we have in LibreOffice, just because they are UNO scripting. And you can easily use them together with the product. And if you want to look into LibreOffice itself, you need to have a build anyway. So they are in the directory for writer SWPA Python. And there's a make file in SWPython test SWPython, which is totally not duplicating anything. And in there is the list of the tests that it should execute. And you can comment out stuff and just run one test or something. And then you can run make this test, and then it runs this specific UNO code. So if you want to debug it, actually find out what is going on inside LibreOffice when you do something with it. You have multiple ways to do that. And the easy way is to pass the enable symbols switch to configure or autogen, which will build the whole thing with symbols. Or you can do something just if you want to have even more details. You can build, for example, a writer in this case in debug mode. And if you do this and together with the other stuff, you can actually debug the Python tests. And I'm going to make two examples here. The first is call grinding these. And usually call grind is a tool to find out, for example, where is my time lost when I do a specific thing. So for performance optimizations and stuff. But you can also just use it for finding out what is actually triggered in my product. Because this is the problem a lot of people have when they first come up to this 10 million lines of code of LibreOffice. And if you have built LibreOffice with these debug symbols, and you have, for example, commented out all the other tests and just have one Python test left in your Python test SWPython file, then you can just do wall grind equals call grind make Python testing. And then we'll run this test on the wall grind. And what this does is that wall grind and call grind notices whatever you call whatever function and counts all the stuff and how much time you spend in everything. And it writes a huge file, which then will be in work via Python test. There's a Python done call, and then there's a file there. And one of them is big. And if you take this file and do this command, it will output you which functions inside of LibreOffice writer have been called by this test. So to explain that, call grind annotate is just analyzing the file. Inclusive yes means that for every function called, you not only want the time and the instructions spent in this specific function, but also all the other functions below it. So if there's just a wrapper function you want all the stuff that is in the wrapper function there too, because you want to know how much time it totally took to enter and exit this function. And you need the threshold 100, because otherwise, it will not give you all the functions. It will skip over some. Then you grab for SW source call unicor, which is writer unibindings. And then you have only the part that is actually called from UNO. And then you just want to have the top 10. And with this, you can find out what a test actually does in writer without having to like control C and then go into the debugger or something like that. And once you have that, you can go debugging the test. I'm going back to that later. So if you do the first thing with, for example, the styles test in writer, you find if you single out a bit and just shorten the paths and stuff like that, you get an output from the command above like this. The first line is just the number of instructions spent in this function. And then you get, you see that SW x-style family getByName is one function that takes a lot of time in this test. And you see that unistyle CXX is the file where it is actually located. So now you know, OK, this test calls wrapper function, which is called getByName and inDatFile. And the others you see too. So with this, you can actually, you now know when you call a unifunction where it ends up in the writer call. And with that, for example, you can do to go back. You can do the second one, which is actually debugging in it. And since you now know which function it is, you can set a breakpoint in this file at this function and get a stack trace after going ahead a few times or something. And if you do that, you get something like this if you break there. At the lowest point, you see this is the unibridge. And there's something comes in. I made this yellow because it is yellow like the services interfaces in this color code that I showed you earlier. And then you have the wrapper function. And that is this blueish, actually now it's kind of greenish, but trust me, it was blue, call, which is the SWX family getElementNames. And if you then just step through it, you actually see what kind of stuff this does in the writer call, which is the stuff above it in Lilac or whatever you call this, call out. And who in the audience is actually familiar with call grind or cache grind? OK, if you force, but not too many. So the file that you generated with this call grind stuff, you can also load into a tool called cache grind, which allows you to travel through this whole thing in a UI mode. And essentially, it's the same as the printed out version, but you can, for example, get a tree like this. And in this case, for example, I highlighted the function, which is the one with a small reddish third box from top. And that is the unicall that is called from the outside. And here you can see what kind of function it all calls all the way down and how much time it spends in each of them. So if you have a performance problem and you know you can look at this or if you just want to know how it all hangs together and what kind of stuff triggers what this might help you. So seeing just from this style test, we see that the interfaces and services were something like ComSanStar text paragraph style. And the unit wrapper is SWX style family, which is what we found out with call grind. And when we debug into it with GDP, we found out that the stuff it does, this wrapper does inside the writer core is using something like SW doc style sheet and SW style sheet iterator and stuff like that. So if you have a bug with your UNO code, you now know where to look for and how to debug into that. Just to make another example, that's another test check table and, well, we see again, OK, there are SWX, whatever, text table, get data, for example, as a function which spends a lot of time. And we also see that a lot of these functions are in UNO TBL CXX. So we know this is the stuff that we want to look for. And if we set break points there, again, we can look what happens here. And again, this is another example of a stack phrase. From inside there, we see the UNO call from outside. And it goes in there, and it does some UNO stuff. And actually, the UNO stuff here calls other UNO stuff, still in the UNO layer. So the wrapper calls other wrappers. And all the way to the top, you'll see, for example, that there's some core code, which is the real writer engine. And if you load this thing in kcache grind, again, you get a wonderful tree that shows you all the functions and relations between all these objects. So from this, for example, you see, again, you have an interface and a service. And UNO wrapper, which is, in this case, for example, is WX cell range. And it's implemented in UNO TBL. And there's a core implementation, which is somehow called from there. So I hope this shows you a bit if you're working with scripting and stuff and want to know more or want to fix bugs or want to help just triaging them how to go about that. Of course, if you have a normal desktop bug and you want to help us triage it, also write tests like that, and you will then also be able to find the code that actually does something. Because finding it via the UI where something is happening might also not be too easy, especially if you have import, export, or stuff like that. OK, questions. No questions. So wasn't that horrible? OK, then thank you.