- Dialog exe

From: Robin McIntosh <macro_at_ihug.co.nz>
Date: Mon, 01 Feb 1999 19:48:31 +1300

Greetings,

During my, often stumbling, efforts to learn how to deal with WINAPI I
have
been working on a stand alone dialog window like HexCalc.f. The code
below is
only a cutdown version of this, (adds two integers entered in two
EDITTEXT
controls) but is sufficient to demonstrate my problem. As the code
stands
it will compile a small dialog window app. and an exe -- testdlg.exe.
The
dialog can be opened interactively using the command - dlg -- and
EDITTEXT
etc. controls respond to Tab and Enter keys as I had planned. However,
when
the exe is opened, the Tab and Enter response turns into error-beeps --
can
anyone explain why?

Also, I tried to use the -APP test from CLICKS.F when processing
WM_DESTROY
but it didn't work for me - after some time playing arround opening the
exe
CtrlAltDel revealed a collection of dead testdlgs. The dev flag,
however,
seems to work.

All the best, Robin.

empty REQUIRES c:\swiftforth\src\options\DLGCLASS

0 VALUE htest

CREATE AppName Z," Test(DlgClass)"

SWITCH: dlg-messages DEFWINPROC ( -- res )

SWITCH: dlg-commands zero

:NONAME MSG LOWORD dlg-messages ; 4 CB: Rundlg

: /dlg-class ( -- hclass ) \ From HexCalc.f
   64 R-ALLOC DUP >R
      [ 0
         CS_OWNDC OR
         CS_HREDRAW OR
         CS_VREDRAW OR
      ] LITERAL !+ \ class style
      Rundlg !+ \ wndproc
      0 !+ \ class extra
      DLGWINDOWEXTRA !+ \ window extra
      HINST !+ \ hinstance
      HINST 100 LoadIcon !+ \ icon
      NULL IDC_ARROW LoadCursor !+ \ cursor
      COLOR_BTNFACE 1+ !+ \ background brush
      0 !+ \ no menu
      AppName !+ \ class name
   DROP R> RegisterClass ;

5 MODELESS AppName [WINDOW (dlg) " Dialog" 100 100 70 80
       (FONT 8, MS Sans Serif) ]
\ [control " default text" id xpos ypos xsiz ysiz ]
   [DEFPUSHBUTTON " OK" IDOK 10 5 50 15 ]
   [EDITTEXT 102 5 20 60 12 ]
   [EDITTEXT 103 5 35 60 12 ]
   [CTEXT 104 6 55 58 11 ]
   [GROUPBOX -1 5 48 60 19 ]

: dlg
   htest ?EXIT
   /dlg-class DROP
   HINST (dlg) 0 0 0 CreateDialogIndirectParam
   DUP TO htest OPENS EXIT
   DISPATCHER DROP ;

:PRUNE
   htest IF htest WM_CLOSE 0 0 SendMessage DROP THEN
   AppName HINST UnregisterClass DROP ;

: .n ( n id -- ) swap >r htest swap r> 0 SetDlgItemInt drop ;

: gocalc ( n -- )
   htest 102 0 0 GetDlgItemInt
   htest 103 0 0 GetDlgItemInt + 104 .n ;

[+SWITCH dlg-commands ( -- res )
   IDOK RUN: gocalc ;
SWITCH]

false value dev

[+SWITCH dlg-messages ( msg -- res )
   WM_CLOSE RUN: hwnd DestroyWindow drop 0 to htest 0 ;
   WM_ACTIVATE RUN: MODELESS-ACTIVATE ;
   WM_COMMAND RUN: WPARAM LOWORD dlg-commands ;
   WM_DESTROY RUN: 0 dev if exit then 0 PostQuitMessage DROP ;
SWITCH]

: WINMAIN ( -- ) dlg DISPATCHER 0 ExitProcess ; ' WINMAIN 'MAIN !

  PROGRAM testdlg true to dev

.

>From rvn_at_forth.com Mon Feb 1 06:27:21 1999
To: sftalk_at_forth.com
Message-Id: <m0000128_at_gerd.forthinc.com>
Subject: Dialog exe
From: "Rick VanNorman" <rvn_at_forth.com>
Date: Mon, 1 Feb 1999 06:27:21 -0800

>Original sender: Robin McIntosh <macro_at_ihug.co.nz>
>
>Greetings,
>
>During my, often stumbling, efforts to learn how to deal with WINAPI I
>have been working on a stand alone dialog window like HexCalc.f. The
>code below is only a cutdown version of this, (adds two integers
>entered in two EDITTEXT controls) but is sufficient to demonstrate my
>problem. As the code stands it will compile a small dialog window app.
>and an exe -- testdlg.exe. The dialog can be opened interactively using
>the command - dlg -- and EDITTEXT etc. controls respond to Tab and
>Enter keys as I had planned. However, when the exe is opened, the Tab
>and Enter response turns into error-beeps -- can anyone explain why?
>
>Also, I tried to use the -APP test from CLICKS.F when processing
>WM_DESTROY but it didn't work for me - after some time playing arround
>opening the exe CtrlAltDel revealed a collection of dead testdlgs. The
>dev flag, however, seems to work.

Robin,
First pass guess without trying to dissect your code:

The management of the tab keys etc is done by the standard dialog message
handler. During development, you were using the SwiftForth dispatch
loop (which is built into PAUSE (which is built in KEY)) which will end
up dispatching via the word IsDialogMessage api. When running stand-alone,
the message dispatcher is simply DISPATCHER which is

: DISPATCHER ( -- res )
   BEGIN
      WINMSG 0 0 0 GetMessage WHILE
      WINMSG TranslateMessage DROP
      WINMSG DispatchMessage DROP
   REPEAT WINMSG 2 CELLS + @ ( wparam) ;

and does not use IsDialogMessage. This is one of the pitfalls of the
technique of using a dialog as a main window.

This is an oversight in the hexcalc example, which I will correct
as soon as possible and post here.

Rick

.

>From mail_at_forthcad.com Mon Feb 1 19:05:17 1999
To: sftalk_at_forth.com
Message-Id: <m0000129_at_gerd.forthinc.com>
Subject: - OOF pre-final
From: ForthCAD <mail_at_forthcad.com>
Date: Mon, 1 Feb 1999 19:05:17 -0000

This is my pre-final OOF system. The final version will be send in +- 3 =
months because I think its now time to use it in reals applications to =
validate some (theorical) choises. Also I must now terminates other =
works...

The system use normals Forth definitions without any preambule nor =
postambule. So there is NO overhead on methods.=20

The overhead on data will be minimized: its just a offset calculation =
always necessary when seeking data in a buffer. (The same in any STRUCT =
systems)

Encapsulation is done by using unnnamed normal Forth wordlist.

Thanks to Will Baden: I think his proposal is very good: its a minimum =
that enable multiple models, with a very clear syntax. ( sometime I =
regret the BUILD word existence, but... )

So I hope this minimum will become near a ANSI standard extension.

Already some extra on the Yerk version are:=20

- easy to write: no multiple SELF, (ouf!)
- easy to read: same syntax as normal Forth, natural word sequence
- fastest: no pre/postambule on methods inside a class
- array of class: (I think Yerk only use "indexed objects" )
- virtual functions with constant small overhead
- true encapsulation: Yerk place all methods in the same vocabulary

(Source from here, wordset description at the bottom)
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ ANSI-CLASS minimum system
\ Version 0.9 - 31/01/1999
\ Author: Charles Melice
\ MAIL: mail_at_forthcad.com
\ WEB: www.forthcad.com
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

ONLY FORTH ALSO DEFINITIONS

\ EMPTY

\ ------------------------------------------------
\ TO DEFINE IF MISSING
\ ------------------------------------------------

\ : @REL POSTPONE @ ; IMMEDIATE
\ : !REL POSTPONE ! ; IMMEDIATE
\ : ,REL POSTPONE , ; IMMEDIATE
\ +TO to replace by equivalence

\ ------------------------------------------------
\ WORDLISTS ENCAPSULATION
\ ------------------------------------------------

WORDLIST CONSTANT CLASS-WORDLIST

CLASS-WORDLIST SET-CURRENT

WORDLIST DUP CONSTANT PRIVATE-WORDLIST

FORTH-WORDLIST SWAP CLASS-WORDLIST 3 SET-ORDER

\ ------------------------------------------------
\ IMPORTANT VALUES
\ ------------------------------------------------

FORTH-WORDLIST SET-CURRENT

0 VALUE THIS \ seek the object-data base
0 VALUE ^CLASS \ seek the in-context class

\ ------------------------------------------------
\ SOME IMPLEMENTATION WORDS
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

CREATE ^PREV-ORDER 33 CELLS ALLOT
0 VALUE PREV-CURRENT

\ used later to define VIRTUAL:=20
DEFER attach-class-vtable
DEFER inherit-to-vtemp

: WID> ( class -- addr ) ; IMMEDIATE
: PARENT> ( class -- addr ) CELL+ ;
: SIZE> ( class -- addr ) CELL+ CELL+ ;
: VTABLE> ( class -- addr ) [ 3 CELLS ] LITERAL + ;

: ^SIZE ( -- addr ) ^CLASS SIZE> ;
: ^VTABLE ( -- addr ) ^CLASS VTABLE> ;
: ^PARENT ( -- addr ) ^CLASS CELL+ ;

: SaveSearchOrder ( -- )
    get-order dup \ s: widn .. wid1 n n
    ^prev-order ! \ s: widn .. wid1 n
    ^prev-order over cells + \ s: widn .. wid1 n addrmax
    swap 0 \ s: widn .. wid1 addrmax n 0
    ?DO dup >r ! r> cell- LOOP
    drop ;

: RestoreSearchOrder ( -- )
    only
    ^prev-order @ 1+ 1 \ s: n 0
    ?DO \ s: -
        i cells ^prev-order +
        @ context ! also
    LOOP
    previous ;

: AlsoClassSearchOrder ( ^class -- )
    dup parent> @rel ?dup \ have a parent ?
    IF RECURSE THEN \ yes -> SetParentClassSearchOrder
    also @ context ! ;

: SetClassSearchOrder ( -- )
    only forth
    also class-wordlist context !
    ^class AlsoClassSearchOrder ;

: ResetClassSearchOrder ( -- )
    ^class
    BEGIN \ s: -
        previous
        PARENT> @REL
        ?dup 0=3D
    UNTIL ;

: ClassView ( ^CLASS -- )
    to ^class SetClassSearchOrder ;

\ ------------------------------------------------
\ CLASS DEFINITION
\ ------------------------------------------------

FORTH-WORDLIST SET-CURRENT

: SUBCLASS ( <<name>> ^parent -- ) \ replace VOCABULARY
    wordlist=20
    create here to ^class \ S: ^parent ^wid
    , \ S: ^parent
    dup ,rel \ S: ^parent
    dup IF size> @ THEN , \ S: - PFA: <wid><parent><size>
    0 ,REL \ vtable^
    SaveSearchOrder
    get-current to prev-current
    SetClassSearchOrder
    ^class wid> @ set-current \ definitions
    inherit-to-vtemp
    DOES> ; ( -- ^CLASS )

: CLASS ( <<name>> -- )
    0 SUBCLASS ;

CLASS-WORDLIST SET-CURRENT

: END ( -- )
    attach-class-vtable
    RestoreSearchOrder
    prev-current set-current ;

\ ------------------------------------------------
\ DATA DEFINITION
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: BUFFER: ( <<name>> size -- )
    create
    ^size @ ,
    ^size +!
    DOES> ( body -- offset+THIS )
        @ this + ;

: VARIABLE ( <<name>> -- ) cell BUFFER: ;

\ ------------------------------------------------
\ SPECIAL WORDLIST LOOKUP
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: SUPER ( <<name>> -- )
    ^class cell+ @rel
    dup 0=3D abort" class have no parent"
    ^class >r to ^class
    previous
    '
    state @
    IF compile, ELSE execute THEN
    r> to ^class
    also ^class wid> @ context ! ;
                                IMMEDIATE

: COMMON ( <<name>> -- )
    RestoreSearchOrder
    '
    state @
    IF compile, ELSE execute THEN
    SetClassSearchOrder ;
                         IMMEDIATE

\ ------------------------------------------------
\ CLASS-OBJECTS INSTANCE
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

\ TODO: Possibles optimisations:
\ case...
\ A - data exist - size > 0
\ B - data exist with offset
\ C - virtual method exist vtable <> 0
\
\ A B C TODO:
\ -- -- -- ---------------
\ 0 0 0 compile,
\ 0 0 1 save-class compile, restore
\ 0 1 0 -
\ 0 1 1 -
\ 1 0 0 compile,
\ 1 0 1 save-class compile, restore
\ 1 1 0 save-this +to compile, restore
\ 1 1 1 save-class-this compile, restore
\

: execute-ivar ( ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ @ +to this
    execute
    2R> to this to ^class ;

: execute-ivar[] ( index ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ @ \ S: index xt offset
    rot ^size @ * + \ S: xt offset+index*size
    +to this
    execute
    2R> to this to ^class ;

: execute-iobj ( ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ to this
    execute
    2R> to this to ^class ;

: execute-iobj[] ( index ^obj xt -- )
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ rot \ S: xt ^base index=20
    ^size @ * + \ S: xt offset
    to this
    execute
    2R> to this to ^class ;

CLASS-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^CLASS -- )
    ^class >R ClassView \ set new class context
    ^size @ ^CLASS \ S: SIZE CLASS
    R> ClassView \ set original class context
    create
    ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    ^size +! \ S: -
    IMMEDIATE
    DOES>
        ^class >r \ save prev context
        dup @REL \ S: ^obj CLASS
        ClassView \ S: ^obj
        ' \ S: ^obj xt=20
        STATE @
        IF
            postpone 2literal
            postpone execute-ivar
        ELSE
            execute-ivar
        THEN
        r> dup to ^class
        ClassView ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    size> @ * ^size +! \ S: -
    IMMEDIATE
    DOES> ( index ^obj -- )
        ^class >r \ save prev context
        dup @REL \ S: index ^obj CLASS
        ClassView \ S: index ^obj
        ' \ S: index ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-ivar[]
        ELSE
            execute-ivar[]
        THEN
        r> dup to ^class
        ClassView ;

FORTH-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^class -- )
    create
    dup ,rel
    here swap \ S: here ^class
    size> @ dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES>
        SaveSearchOrder
        dup @REL \ S: ^obj CLASS
        ClassView \ S: ^obj
        ' \ S: ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-iobj
        ELSE
            execute-iobj
        THEN
        RestoreSearchOrder ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,rel \ S: count ^class
    size> @ * \ S: count*size
    here swap \ S: here count*size
    dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES> ( index ^obj -- )
        SaveSearchOrder
        dup @REL \ S: index ^obj CLASS
        ClassView \ S: index ^obj
        ' \ S: index ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-iobj[]
        ELSE
            execute-iobj[]
        THEN
        RestoreSearchOrder ;

   =20

\ ------------------------------------------------
\ (optional) VIRTUAL: ( <<name>> -- )
\ define a virtual method
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

100 constant MAX-VIRTUAL

create vTblTemp 0 , MAX-VIRTUAL 2* cells allot

: virt-count ( -- addr )
    ^VTABLE @REL ;

: vtable[] ( n -- addr )
    2* 1+ cells virt-count + ;

:noname [ IS inherit-to-vtemp ] ( -- )
    0 vTblTemp !
    ^parent @REL
    IF
        ^class >r
        ^parent @REL to ^class
        ^vtable @REL
        IF
            virt-count @ vTblTemp !
            vTblTemp cell+
            virt-count @ 0
            ?DO
                i vtable[] @REL over !REL
                cell+
                i vtable[] cell+ @REL over !REL
                cell+
            LOOP
            drop
         THEN
         r> to ^class
    THEN
    vTblTemp ^vtable !REL ;

:noname [ IS attach-class-vtable ] ( -- )
    virt-count @
    IF
        here
        virt-count dup @ \ S: body addr count
        dup , 0 \ S: body addr count 0
        ?DO \ S: body addr
            cell+ dup @REL ,REL
            cell+ dup @REL ,REL
        LOOP
        drop
        ^vtable !REL
     ELSE
        0 ^vtable !REL
     THEN ;
           =20

: in-vtable ( body^ -- pos true | false )
    virt-count @ 0
    ?DO
        i vtable[] cell+ @REL over =3D
        IF drop i TRUE unloop EXIT THEN
    LOOP
    drop FALSE ;

: append-to-vtable ( body^ -- n )
    \ later, we should use allocate/resize
    virt-count @
    dup MAX-VIRTUAL >=3D abort" virtual table overflow - see =
MAX-VIRTUAL"

    vtable[] cell+ !REL
    virt-count @
    dup 1+ virt-count ! ;

: CreateVirtual: ( <<method>> -- vn )
    Create here \ S: bod
    append-to-vtable \ S: vn
    dup 2* 1+ cells , \ S: byte-offset
                            \ offset in bytes to speed-up
    DOES> \ TODO: better optimisation
        @ ^vtable @REL + \ this is the virtual overhead
        @REL execute ;=20

\ ------------------------------------------------
\ Extra words - not defined in ANSI proposal
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: VIRTUAL: ( <<name>> -- )
>IN @
    bl word find
    IF \ S: in^ xt
>body in-vtable
        IF
            nip \ S: vn
        ELSE
>IN !
            CreateVirtual: \ S: vn
        THEN
    ELSE \ S: in^ cstr
        drop >IN ! \ S: -
        CreateVirtual: \ S: vn
    THEN
    :noname swap \ S: xt vn
    vtable[] !REL ;
       =20

FORTH-WORDLIST SET-CURRENT

: >THIS ( ^object -- ^membase ) \ usage ' obj >this
>body cell+ ;

: >CLASS ( ^object -- ^class ) \ usage ' obj >class
>body @REL ;

: USER> ( ^class -- addr ) \ ' obj >class user> @
    [ 4 CELLS ] LITERAL + ;

: NEW ( ^class -- ^obj )
    dup SIZE> @ cell+
    allocate abort" memory allocation error"
    swap over !REL ;

: NEW[] ( count ^class -- ^obj )
    dup SIZE> @ rot * cell+
    allocate abort" memory allocation error"
    swap over !REL ;

\ FREE DROP can be used - so no collision with RELEASE

: ->" ( <<obj]>> <<method>> -- )
    [char] " word count evaluate
    ^class >R
    dup @REL to ^class \ S: ^obj
    ^class AlsoClassSearchOrder
    ' \ S: ^obj xt
    state @
    IF
        postpone 2literal
        postpone execute-iobj
    ELSE
        execute-iobj
    THEN
    ResetClassSearchOrder
    R> to ^class ;
                    IMMEDIATE

: []->" ( index <<obj]>> <<method>> -- )
    [char] " word count evaluate
    ^class >R
    dup @REL to ^class \ S: index ^obj
    ^class AlsoClassSearchOrder
    ' \ S: index ^obj xt
    state @
    IF
        postpone literal
        postpone execute-iobj[]
    ELSE
        execute-iobj[]
    THEN
    ResetClassSearchOrder
    R> to ^class ;
                    IMMEDIATE

: .CLASSINFO ( ^class -- )
    SaveSearchOrder
    cr 0 >r
    BEGIN
        dup body> >name count
        swap over cr r@ spaces type cr
        r@ spaces 0 ?DO [char] - emit LOOP
        dup wid> @ context !
        cr r@ spaces words cr
        parent> @rel ?dup 0=3D
        r> 3 + >r=20
    UNTIL
    r> drop
    RestoreSearchOrder ;

: SIZEOF ( ^class -- size )
    size> @ ;

ONLY FORTH ALSO DEFINITIONS

\ ------------------------------------------------
\ SOURCE END
\ ------------------------------------------------

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DWil Baden ANSI Class wordset =
proposal=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

CLASS
    CLASS class
    Construct a class.
    A class is a defining word for a collection of future definitions.

SUBCLASS
    class SUBCLASS classname
    Construct an extension or specialization of a class.

VARIABLE WITHIN A CLASS
    VARIABLE membername
    Define a variable member of a class.

BUFFER: WITHIN A CLASS
    n CHARS BUFFER: membername
    n CELLS BUFFER: membername
    Define a data area member of a class.

CONSTANT WITHIN A CLASS
    n CONSTANT membername
    Define a constant member of a class.

: WITHIN A CLASS
    : membername ... ;
    Define a function member of a class.

; WITHIN A CLASS
    : membername ... ;
    Terminate the definition of a function member of a class.

END WITHIN A CLASS
    END
    Terminate the construction of a class.

BUILD
    class BUILD objectname
    Build object objectname as an instance of class .
    Objects are used object member .

COMMON WITHIN A CLASS
    COMMON forthword
    Compile forthword from standard dictionary.

SUPER WITHIN A CLASS
    SUPER member
    Compile a member, beginning lookup for it in the superclass.
    This disambiguates members with the same name.

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DMy extension in the above =
 object base memory adress.

^CLASS
    This value return the context class body adress.

.
Received on Mon Feb 01 1999 - 19:48:31 PST


Subscribe to our e-mail list service. It's free for all SwiftForth and SwiftX users!

This archive was generated 09-Feb-2012. Archive updated nightly.