lispnik / iup

Common Lisp CFFI bindings to the IUP Portable User Interface library (pre-ALPHA)
Other
139 stars 7 forks source link

IupScintilla attributes ending in numbers missing #62

Closed oliverdelancey closed 11 months ago

oliverdelancey commented 11 months ago

I've been really enjoying using this library, and started working on a text editor component of my software. Here I ran into a bit of an issue:

Pretty much the title. Certain IUP attributes don't exist as lisp keywords in the definition of (iup-scintilla:scintilla), whereas keywords like :lexerlanguage or :value do exist.

For instance, "KEYWORDS0" sets a list of keywords for Scintilla to highlight, but there is no :keywords0 in (iup-scintilla:scintilla). And attempting something like (setf (iup:attribute *editor* :keywords0) "defun defclass") silently does nothing, as well as trying it as "KEYWORDS0".

This seems to be the case for any iup (scintilla) attributes that end with a number, such as "KEYWORDS0", "STYLEFONT32", "STYLEFGCOLOR5", etc.

IupScintilla documentation: https://www.tecgraf.puc-rio.br/iup/en/ctrl/iup_scintilla.html

oliverdelancey commented 11 months ago

The plot thickens... I wrote a quick little testing program in C to get the list of attributes that IUP actually "publishes" for IupScintilla.

#include <stdlib.h>
#include <stdio.h>

#include "include/iup.h"
#include "include/iup_scintilla.h"

int main(int argc, char** argv)
{
    IupOpen(&argc, &argv);

    Ihandle *sci;
    IupScintillaOpen();
    sci = IupScintilla();
    char* scname = IupGetClassName(sci);
    char* sctype = IupGetClassType(sci);
    printf("classname: %s\n", scname);
    printf("type: %s\n", sctype);

    int max_names = 1000;
    char* names[max_names];
    int c = IupGetClassAttributes(scname, names, max_names);
    printf("count: %i\n", c);
    if (c != -1) {
        for (int i=0; i<c; i++) {
            printf("name: %s\n", names[i]);
        }
    }
    IupClose();
    return EXIT_SUCCESS;
}

and it gives the "missing" attributes, but without any numbers appended:

...
name: KEYWORDS
...
name: KEYWORDSETS
...
name: STYLEFONT
...
etc

So why is (cffi:defcfun (%iup-get-class-attributes "IupGetClassAttributes") ... not picking these up?

oliverdelancey commented 11 months ago

Eureka! After much searching through the code, I have come upon the answer. In classes.lisp, I found this line (thanks to @vindarel for pointing me in the right direction): https://github.com/lispnik/iup/blob/353bd1e5d3602550b7f589cabd74cbf7c2f4d884/iup/classes.lisp#L107 At first this worried me, because this simply drops all attributes with an id. So I searched for "id" in hopes of finding more removal/filtering related stuff, and found this gem: https://github.com/lispnik/iup/blob/353bd1e5d3602550b7f589cabd74cbf7c2f4d884/iup/attributes.lisp#L71 and an example of its usage here: https://github.com/lispnik/iup/blob/353bd1e5d3602550b7f589cabd74cbf7c2f4d884/examples/tree-demo.lisp#L120

Armed with this knowledge, I was able to successfully translate part the example IupScintilla C program into the following:

(defun main-gui ()
  (iup:with-iup ()
    (iup-scintilla:open)
    (let* ((editor (iup-scintilla:scintilla
                     :visiblelines 20
                     :visiblecolumns 60))
           (vbox (iup:vbox (list editor)
                           :gap "10"
                           :margin "10x10"
                           :alignment :acenter
                           :expandchildren :yes))

           (dialog (iup:dialog vbox :title "Scintilla Test")))
      (setf (iup:handle "editor") editor)

      (setf (iup:attribute-handle nil :parentdialog) dialog)

      (iup:show dialog)

      (setf (iup:attribute editor :clearall) ""
            (iup:attribute editor :lexerlanguage) "cpp"
            (iup:attribute-id editor :keywords 0) "void struct"
            (iup:attribute-id editor :stylefont 32) "Consolas"
            (iup:attribute-id editor :stylefontsize 32) "12"
            (iup:attribute editor :styleclearall) :yes
            (iup:attribute-id editor :stylefgcolor 1) "0 128 0"
            (iup:attribute-id editor :stylefgcolor 2) "0 128 0"
            (iup:attribute-id editor :stylefgcolor 4) "128 0 0"
            (iup:attribute-id editor :stylefgcolor 5) "0 0 255"
            (iup:attribute-id editor :stylefgcolor 6) "160 20 20"
            (iup:attribute-id editor :stylefgcolor 7) "128 0 0"
            (iup:attribute-id editor :stylefgcolor 9) "0 0 255"
            (iup:attribute-id editor :stylefgcolor 10) "255 0 255"
            (iup:attribute-id editor :stylebold 10) :yes
            (iup:attribute-id editor :stylehotspot 6) :yes)
      (iup:main-loop)))
  (uiop:quit))

Note that it is important to place these attribute-id calls after (iup:show ...) for whatever reason. If you call them before, they don't seem to apply... (except :stylefontsize ???).

I made a repo with a little example program here.

Marking as closed.

vindarel commented 11 months ago

Well done!!