ver 0.9.0 issue

Started by James C. Fuller, March 31, 2025, 12:40:20 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

James C. Fuller

Charles,
  Attached compiles and runs fine with 0.8.0 2025-02-19

James

Charles Pegge

Hi James,

I found some logistical problems with macro  '=' default values, so I had to withdraw this feature. but you can still test any macro parameter, and provide a default definition/value:

'Macro LineInput string (s,c,b=1024)
Macro LineInput string (s,c,b)
        #ifndef b
          % b=1024
        #endif
s = nuls b
s = (char*)fgets(s,b,c)
End Macro

Roland Stowasser

Hi Charles,

I also have problems with version 0.9.0 2025-03-31. If I run the demos in folder ... WinGUI\Autosizing I get error messages like: Undefined Symbol: maxpinned.count. If I run in !ProjB\Console\AsciTetris the app, the program will not run correctly or not at all, showing an error message with unidentified names.
I replaced oxygen.dll 0.9.0 with oxygen.dll 0.8.0 and everything works fine. I am not sure if I have to modify anything with the .o2bas or .inc files?

I only tested with oxygen.dll 32-bit and only these applications. Are changes to the programs necessary for 0.9.0?

Charles Pegge

#3
Thanks Roland,

I've fixed 2 problems exposed by your code.

One affected redims using an object member as an index.

The other was an unwanted (internal) macro symbol case conversion.

I've also restored macro default values, so James' original example now works.

I made over 60 changes for version 0.9.0. The main ones are to remove the upper limit on primary symbol count (was 32k) by using dynamic storage. Also to make macro compiling more efficient. I also discovered a memory overflow bug which could destabilize larger compilations.

QuoteRELEASE 0.9.0

16:14 01/04/2025 Fix macro symbol case-matching (himac icase=1)
16:12 01/04/2025 Fix dynamic array index (ert=504)
00:51 01/03/2025 Reduce code for function defaults (subsas)
18:16 31/03/2025 Restore Macro default values. New code. (Himac w5)
12:02 31/03/2025 Remove string initializers (reco.inc strini strinr)
02:33 31/03/2025 Fix records clearing size (reco.inc init4 @drc)
09:22 30/03/2025 Dynamic Records (reco.inc maxit)
02:51 30/03/2025 Fix records member int sizes .a and .f (reco.inc)
17:12 28/03/2025 Reduce nest/unnest staticvars etc (reco.inc)
13:49 28/03/2025 Fix 'unnest' to always retain local space (reco.inc lclr)
02:05 26/03/2025 Change namespace symbol from '..' to '::' (colom setnamespace)
20:15 23/03/2025 Revoke checking for colons in single line type statements (tran.inc " : ")
11:39 23/03/2025 Revoke recursion/expansion for deff macros. (expr.inc  expandfmac)
22:20 21/03/2025 Fix higher type '+='  '*='  macros (tran.inc expr.inc cpa>2)
04:56 21/03/2025 Fix higher function return copy (rps=16)
16:52 20/03/2025 Optimize Higher types assignment (tran.inc accg)
22:20 17/03/2025 Inhibit macro param case conversion (parse.inc lomac icas=1)
22:10 11/03/2025 Implement more efficient namespace resolution (reco.inc dotm))
15:53 10/03/2025 Implement nested namespace without leading '..' (reco.inc nss nk))
11:04 10/03/2025 Implement %0 unique symbol substitution in def macros (lomac)
11:03 10/03/2025 Revoke %% escape check in def macros. (lomac)
03:38 09/03/2025 Support d[1]={...} : n=countof (massign elct)
14:16 08/03/2025 Revoke default values in macros (pars.inc himac)
15:42 07/03/2025 Implement #unquote (pars.inc mword() )
11:55 07/03/2025 Remove ##. from OpenglScrnrFrame.inc etc macros
01:44 07/03/2025 Rework himac and replacewd / macro (pars.inc lexi.inc)
20:40 04/03/2025 Revoke embedfile (ebd)
22:16 03/03/2025 Support infinity as a variable (lang.inc)
22:04 03/03/2025 Implement initialization macro (lang.inc tran.inc)
17:44 03/03/2025 Changes in lang.inc: pow and exp (lang.inc ~~~)
00:51 01/03/2025 Prevent peroxide terminating on escape key (27) (peroxide.o2as)
21:20 28/02/2025 Support 'foreach x x[ i ]= ...' (lang.inc)
21:20 28/02/2025 Support 'on x gosub/goto' (lang.inc)
21:20 28/02/2025 Support 'view x' (lang.inc)
21:20 28/02/2025 Support 'stretch x(n)' (lang.inc)
21:20 28/02/2025 Support 'dyn int x(n)' (lang.inc)
21:09 28/02/2025 Support '#tally {1,2,3 ...}' (pars.inc)
12:37 28/02/2025 Revoke 'inner', use 'scope' instead (lang.inc)
12:06 28/02/2025 Improve 'anymatch' (meta.inc anymatch idword)
02:42 28/02/2025 Rearrange records structure (reco.inc records)
02:34 27/02/2025 Fix detection of excess left bracket in classes etc (nocapt)
19:40 26/02/2025 Extend #show to display resolved macros (pars.inc shd...)
11:20 25/02/2025 Fix redim zc  / idx / mf (glo2\graphicOjects.inc)
03:12 24/02/2025 Annotation of code in #show (enco.inc shd)
19:12 23/02/2025 Change asm loading literal numbers 64it (CheckLiteral)
19:09 23/02/2025 Display variale names in #show (shd)
23:19 22/02/2025 Enable all dynamic arrays to define multidims (rarray)
23:19 22/02/2025 Remove array Attribs table from class _table (no vot)
23:19 22/02/2025 Fix flagsof() on undefined variable ('flagsof)
05:43 22/02/2025 Support simple arrays without attribs table ( _dims_ )
05:43 22/02/2025 Fix dynamic arrays (ert=503)
04:40 21/02/2025 Expand capacity from 32k to 128k symbols etc (maxit)
05:17 19/02/2025 Fix on .. macro params (lang.inc)
05:17 19/02/2025 Fix goto/gosub labels/variables (tran.inc 'goto fwd)
20:02 18/02/2025 Undef insturction extended to block labels (o2 z)
04:56 18/02/2025 Support ForEach x {x[ i ]=...} (lang.inc)
01:24 18/02/2025 Fix #unique: allow function overloads and declarations (rec.inc -5)
23:09 17/02/2025 Support 'view' macros (lang.inc)
20:28 17/02/2025 Change messagebox title from O2H to O2H (mbox RTL32/64)
16:58 17/02/2025 Support 'on' macro for on gosub/goto (lang.inc)
02:42 15/02/2025 Fix register spills for ms64 byval h params (typq aprm))
20:17 13/02/2025 Support pseudo-variable assignment with default param functions (subsas)
11:15 12/02/2025 Changes to Manual (oxyDatabase.inc OxygenBasic_Manual.chm)
05:34 10/02/2025 Support subroutines to always retain local space (lclr)
14:58 06/02/2025 Support dim c as asciiz*20*10 (rmuldim:)

Roland Stowasser

Hi Charles,

these are really a lot of Innovations and it will take some time to test them all.

Unfortunatelly the AsciTerix.o2bas app still does not work correctly. The shape on the left side does not correspond to the shape of the right side. Moreover the shape leaves the ground on the left side, and nothing works any more..

Demo1.o2bas and SmallApp.o2bas of the Autosizing folder work as expected, but the sizing of demo2, demo3, demo4, demo5, demo6 does not happen.

Demo4.o2bas also show errors like: Cannot find hCtl: 590640in PinCtl_Rec, hctl: 329524 in PinCtl_Rec
Demo7Dlg.o2bas shows an error in line 32: Unidentified element type: WORD type... The app then terminates

As these apps work fine with version 0.8.0 I have not yet started further examination.

I also noticed that in console mode printl  without argument does not work anymore. This form is used in testlog2.o2bas and testlog3.o2bas too.
I found in Console.inc:

  function printl(cstr_*s="")
  '==========================
  output s cr
  end function

In ConsoleG.inc there is:

  sub printl(optional string s)
  =============================
  output s,1.0
  end sub

Does this make a difference?

Theo Gottwald

#5
@Charles Pegge recommend that you try Googles AI-Studio.
https://aistudio.google.com/prompts/new_chat
it has up to  MB Kontextwindow, means you can just drop your whole code and ask "Where are the bugs"".
It may even return you the corrections needed. Give it a try.

Of course googe wil lcollect code this way to train their systems.
But ... our code is not a secret.
I saved hours or days of coding and bug-searching.
Just dropped the not working Sub into google ... got the corrected code back.
Together with a commentblock.

TIP: If you have special coding wishes write them into the system prompt at the top of the page.

TIP: It will also write your helpfiles. Drop it the source code of the commands .... and a sample of the format of your help file. Thats all, it will then write the XML-Code (or whatever you like) for your helpfile.
Help file writing is most annoying. I am so happy AI does it.

Roland Stowasser

I get strange messages:

Edge:
Hmmm...diese Seite ist leider nicht erreichbar
Überprüfen Sie, ob in ai-studio ein Tippfehler vorliegt.

Im Web nach ai-studio suchen

Another Browser:

Diese Website ist nicht erreichbar
Prüfe, ob ,,ai-studio" einen Tippfehler enthält.

Wenn die URL keinen Tippfehler enthält, kannst du die Windows-Netzwerkdiagnose durchführen.
DNS_PROBE_FINISHED_NXDOMAIN

Heading:
Website not safe

Charles Pegge

#7
At last I've fixed THE issues with redim and macro which caused problems with your autosizing and Tetris demos.

The only change that needs to be made is to reformat the single liner types in demos\WinGUI\Autosizing\Demo7dlg.o2bas. Colons in types are no longer supported. Just use commas. but for easier reading, the larger types should be presented in the standard block format.

type TCITEM int mask,dwState,dwStateMask, char* pszText, int cchTextMax,iImage, sys lParam

typedef TCITEM TC_ITEM

type TBADDBITMAP , sys hInst , sys  nID

type TBBUTTON , int iBitmap , int idCommand , BYTE fsState , BYTE fsStyle , dword dwData , sys iString

Further update fixing James' console print problem. Macros handling complex expression params:


Roland Stowasser

Hi Charles,

I downloaded Oxygenbasic.zip version 0.09.0 2025-04-04T15:04. AsciTerix works fine, also AsciTerix2 where you used different coding variations. But I suppose the Home - Shortcut is superfluous?

Checking the demos in the WinDynDialogs folder, most of the apps work fine. But I noticed that in Listview.o2bas there is an error message:
ERROR:    unclosed brackets at end of script (1)
COL:    1
LINE:    271
FILE:    "main source"

Moreover Pgbar3d.o2bas and Pgbar3d3.o2bas do not run at all. As all the demos work fine with version 0.8.0 I am not sure if there are changes like with the single liner types, which must be taken into account, or if there is something missing in oxygen.dll. Hopefully you do not think that I am lazy.


Roland Stowasser

Hi Charles,

I found the missbehaviour of Listview.o2bas in function AboutDlgProc in line 116, 117. If I modify this:

'      if loword(wParam) = IDCANCEL or
'        loword(wParam) = IDOK then
      if loword(wParam) = IDCANCEL or loword(wParam) = IDOK then

then the app will run. But I think line 116, 117 should also work?

Nevertheless there is a mistake in line 201 / 202 also. The line should read.

              Dialog( 0,0,144,77, "About Listview Sample", 


So this would be the interim code:

'====================================================================
' Listview example, nested modeless dialog.
'====================================================================


$ filename "ListView.exe"
'uses rtl32
'uses rtl64

'% review

uses dialogs


'Identifiers
#define IDD_DLG1 1000
#define IDC_LSV1 1001
#define IDM_EXIT        104
#define IDM_ABOUT       105
#define IDI_LOGO        106


macro ListView_InsertColumn(hwnd,iCol,pcol) (SendMessage(hwnd, LVM_INSERTCOLUMN, iCol, pcol))
macro ListView_SetColumnWidth(hwnd,iCol,cx) (SendMessage(hwnd, LVM_SETCOLUMNWIDTH, iCol, cx))
macro ListView_InsertItem(hwnd,pitem) (SendMessage(hwnd, LVM_INSERTITEM,0, pitem))
macro ListView_SetItem(hwnd,pitem) (SendMessage(hwnd, LVM_SETITEM,0, pitem))

% DS_CENTER=0x0800
% DS_MODALFRAME=0x80
% SS_CENTERIMAGE=0x200
% LVS_LIST  0x0003
% LVS_REPORT  0x0001
% LVS_EX_GRIDLINES 1
% LVS_EX_CHECKBOXES 4
% LVS_EX_FULLROWSELECT  0x0020
% LVSCW_AUTOSIZE  -1
% LVSCW_AUTOSIZE_USEHEADER  -2
% LVM_INSERTCOLUMN=4123
% LVM_SETCOLUMNWIDTH=4126
% LVM_INSERTITEM=4103
% LVM_SETITEM=4102
% LVCF_FMT 1
% LVCF_WIDTH 2
% LVCF_TEXT=4
% LVCF_SUBITEM 8
% LVIF_TEXT=1
% LVM_SETEXTENDEDLISTVIEWSTYLE 0x1036
% LVN_COLUMNCLICK = -108
% LVN_ITEMCHANGED = -101
% LR_LOADFROMFILE=0x0010
% IMAGE_ICON=1
% STM_SETIMAGE=0x172
% SWP_NOZORDER=4

type LVCOLUMN
  uint  mask
  int   fmt
  int   cx
  char* pszText
  int   cchTextMax
  int   iSubItem
  int   iImage
  int   iOrder
  int   cxMin
  int   cxDefault
  int   cxIdeal 
end type
typedef LVCOLUMN LV_COLUMN

type LVITEM 
  uint   mask
  int    iItem
  int    iSubItem
  uint   state
  uint   stateMask
  char*  pszText
  int    cchTextMax
  int    iImage       // index of the list view item's icon
  sys    lParam       // 32-bit value to associate with item
  int    iIndent
  int    iGroupId
  uint   cColumns
  uint   *puColumns
  int    *piColFmt
  int    iGroup
end type
typedef LVITEM LV_ITEM

% LVROWS = 200   ' Number of rows in the ListView
% LVCOLS = 3     ' Number of columns in the ListView

! GetDlgItem lib "user32.dll" (sys hDlg, int nIDDlgItem) as sys
! IsDialogMessage lib "user32.dll" alias"IsDialogMessageA" (sys hDlg, sys lpMsg) as bool
! IsWindow lib "user32.dll" (sys hWnd) as bool


sys AboutDlg
'string o2dir = "c:\oxygenbasic\"
string o2dir = "..\..\"
string fullname


init_common_controls()

function AboutDlgProc( sys hDlg, uint uMsg, sys wParam, lParam) as sys callback

  select case uMsg

    case WM_INITDIALOG
      fullname = o2dir + "tools\OxideIcon.ico"
      sys hIcon = LoadImage( 0, fullname, IMAGE_ICON,0,0, LR_LOADFROMFILE )
      if hIcon=null then mbox "Cannot load " + fullname +"!"
      SendMessage (GetDlgItem(hDlg,IDI_LOGO), STM_SETIMAGE, IMAGE_ICON, hIcon)

    case WM_COMMAND
'      if loword(wParam) = IDCANCEL or
'         loword(wParam) = IDOK then
      if loword(wParam) = IDCANCEL or loword(wParam) = IDOK then
        DestroyWindow( hDlg )
      end if

    case WM_CLOSE
      DestroyWindow( hDlg )

      'Reset so main can determine if nested dialog is open.
      AboutDlg = 0

  end select

  return 0
end function

'====================================================================

function DlgProc( sys hDlg, uint uMsg, sys wParam, lParam ) as sys callback

  sys hMenu
  sys hListview = GetDlgItem(hDlg, IDC_LSV1) 
  int i,j
  LV_COLUMN lvc
  LV_ITEM lvi
  select case uMsg

     case WM_INITDIALOG
        MENU(hMenu)
       
        BEGIN
          POPUP "&File"
          BEGIN
            MENUITEM "E&xit",IDM_EXIT
          ENDMenu
          POPUP "&Help"
          BEGIN
            MENUITEM "&About...",IDM_ABOUT
          ENDMenu
        ENDMenu

        if SetMenu( hDlg, hMenu ) = 0 then
          mbox "SetMenu hMenu failed!"
        end if

        string text
        'Column Headers
        For i = 0 To LVCOLS
           lvc.mask = LVCF_FMT OR LVCF_WIDTH OR LVCF_TEXT OR LVCF_SUBITEM 'LVCF_TEXT
           text="Column #" & str(i+1)
           lvc.pszText = text               
           ListView_InsertColumn(hListview, i, &lvC)
        Next i

        'Rows
        For i=1 To LVROWS
           'First column
           lvi.mask      =  LVIF_TEXT
           text = "Row #" & str(200-i+1) ", Col # 1"
           lvi.pszText   = text
           lvi.iSubItem  =  0
           ListView_InsertItem(hListview, &lvi)
           'Remaining columns
           for j=2 to LVCOLS
              text = "Row #" & str(200-i+1) ", Col # " & str(j)
              lvi.pszText   = text
              lvi.iSubItem  =  j-1
              ListView_SetItem(hListview, &lvi)
           next j
        Next i

        for i = 0 to LVCOLS
           ListView_SetColumnWidth(hListview,i,LVSCW_AUTOSIZE_USEHEADER)
        next i
       
        SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,  LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES)
'        SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,  LVS_EX_GRIDLINES)
'        SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,  LVS_EX_CHECKBOXES)
         
    case WM_COMMAND

       select case loword(wParam)
          case IDM_ABOUT
            'Open nested dialog only if not already open.
            if IsWindow( AboutDlg ) = 0 then           
              Dialog( 0,0,144,77, "About Listview Sample",
                      WS_POPUP|WS_VISIBLE|WS_CAPTION|DS_MODALFRAME or DS_SETFONT or DS_CENTER,
                      8,"MS Sans Serif" )
              CONTROL "OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,54,51,40,14
              CONTROL "Creating a Listview Control",-1,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP, 50,17,92,8
              CONTROL "in OxygenBasic",-1,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,65,27,70,8
              Control(  "",IDI_LOGO, "STATIC", SS_ICON|SS_CENTERIMAGE, 0, 0, 40, 40 )
              AboutDlg = CreateModelessDialog( hDlg, @AboutDlgProc, 0 )
            end if

        case IDCANCEL, IDM_EXIT
           DestroyWindow( hDlg )
        end select

    case WM_NOTIFY
       NMHDR pnm at lParam
       
       if pnm.hwndFrom = hListview then      'ListView         
            select case pnm.code
              case LVN_COLUMNCLICK
mbox "LVN_COLUMNCLICK"                           
              case LVN_ITEMCHANGED
#ifdef review
  printl "LVN_ITEMCHANGED"
  printl
#endif             
            end select
       end if
 

      case WM_SIZE     
         RECT rcClient
     
         // Calculate remaining height and size edit
         GetClientRect(hDlg, &rcClient)
         SetWindowPos(hListview, NULL, 0, rcClient.top, rcClient.right, rcClient.bottom, SWP_NOZORDER)

    case WM_CLOSE
      DestroyWindow( hDlg )

    case WM_DESTROY
      PostQuitMessage( null )

  end select

  return 0
end function

'====================================================================

sys hDlg
MSG wMsg

Dialog( 10,10,280,150, "Listview example",
        WS_OVERLAPPEDWINDOW or DS_CENTER or WS_VISIBLE,
        8,"MS Sans Serif" )

CONTROL "",IDC_LSV1,"SysListView32", _
        WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER|LVS_REPORT, _
        3,3,273,141,WS_EX_CLIENTEDGE

hDlg = CreateModelessDialog( 0, @DlgProc, 0 )

while GetMessage( @wMsg, null, 0, 0 ) <> 0
  if IsDialogMessage( hDlg,  @wMsg ) = 0 then
    if IsDialogMessage( AboutDlg,  @wMsg ) = 0 then
      TranslateMessage( @wMsg )
      DispatchMessage( @wMsg )
    end if
  end if
wend

Charles Pegge

Thanks Roland,

I've corrected the compiler so it will read the 'or' split expression correctly again (line 116/117 Listview.o2bas).

But I am still baffled by the GPF triggered by:
hBar = CreateWindowEx(... in Pgbar3d.inc.

Roland Stowasser

Hi Charles,

that seems to be a bit tricky. I searched in the demos for apps with CreateWindowEx statement. Most of them seem to work fine. I found difficulties with:

\demos\Sound\WhoNext.o2bas - runs fine with 0.8.0 2025-02-19,
with 0.9.0 2025-04-04T 15:04 the text on labels does not work, after some time the app crashes

\demos\WinGui\BurningControl.o2bas - message that registering fails, and control does not work - neither in  version 0.8.0
\demos\WinGui\Doublebuff1(2).o2bas - message that registering fails, but works nevertheless(?), same with 0.8.0

The  apps work with older versions of oxygen.dll, but replacing the dll in the latest release does not work, because the structure of the include files has changed too much.

Roland Stowasser

I am a little confused. After installing a new Oxygenbasic.zip version 0.8.0 2025-02-19T05:08:06 in a separate folder, I ran all the demos again in this folder with Oxide. There was no problem with any of the demos also not with the Pgbar3d(3) demos. I thought it would be sufficient to replace the oxygen.dll in the 0.9.0 folder, but this is not true. 

Charles Pegge

#13
Hi Roland,

 I find that Windows is quite capable of using the wrong DLL - very confusing when switching DLL versions.

With regard to CreateWindowEx in Pgbar3d, the GPF is actually triggered in PgbWndProc.

     case PGB_GETGRADIENTDIR
return 1
'return 0 'horizontal gpf
        return pgb.gradientDir       'return gradient direction

But there is nothing wrong with this procedure that I can see. The gpf is avoided if I return 1. So the problem is on the outside.



I found a few problems with demos\Sound\WhoNext.o2bas, so I made some changes and rewrote the WM_TIMER section. I avoids multiple iterations of SetWindowText calls, and seems to have cleared the problem.

    $ filename "Lyrics.exe"
     
    'uses rtl32
    'uses rtl64
     
    uses WinUtil
    'uses console
    indexbase 1
     
    % DS_MODALFRAME=128
    % GCLP_HBRBACKGROUND= -10
    % COLOR_3DFACE=15
     
    extern lib "winmm.dll"
    ! mciSendString "mciSendStringA"    '4
    end extern
     
    declare sub loadlyrics()
     
    redim bstring lyrics[30]
    sys lbl[5]
     
    loadlyrics()
     
    sys hInstance=inst
    MainWindow 400,220, DS_MODALFRAME OR WS_POPUP OR WS_CAPTION OR WS_SYSMENU
     
     
    function WndProc(sys hwnd, uMsg, wParam, lParam) as sys callback
    int unit, x
     
        select uMsg
            case WM_CREATE
                static string temp=space 256
                SetWindowText(hwnd, "Tom Lehrer - Who's next")
                'Adjust color of MainWindow
                SetClassLongPtr(hwnd,GCLP_HBRBACKGROUND, GetSysColorBrush(COLOR_3DFACE))
                char cts="static"
                int sty=WS_CHILDWINDOW | WS_VISIBLE           
                lbl[1]=CreateWindowEx(0,cts,"",sty, 20, 30,360,25, hwnd,0,hinstance,0)
                lbl[2]=CreateWindowEx(0,cts,"",sty, 20, 55,360,25, hwnd,0,hinstance,0)
                lbl[3]=CreateWindowEx(0,cts,"",sty, 20, 80,360,25, hwnd,0,hinstance,0)
                lbl[4]=CreateWindowEx(0,cts,"",sty, 20,105,360,25, hwnd,0,hinstance,0)
                lbl[5]=CreateWindowEx(0,cts,"",sty, 20,130,360,25, hwnd,0,hinstance,0)
           
                mciSendString("open whonext.mid type sequencer alias whonext", 0, 0, 0)
                mciSendString("status whonext length", temp, 256,0)
                unit=val(temp)
                if unit=0 then
                  mbox "Cannot open whonext.mid. Sorry!"
                  SendMessage(hwnd, WM_CLOSE,0,0)
                end if 
                if unit !=759 then
                  mbox "Wrong midi file. Sorry!"
                  SendMessage(hwnd, WM_CLOSE,0,0)
                end if 
     
                mciSendString("play whonext", 0, 0, 0)
     
                SetTimer(hwnd,1000,10,0)
    /*
            'check the position
            case WM_LBUTTONDOWN
                mciSendString("status whonext position", temp, 256,0)
                unit=val(temp)
                printl unit
    */
            case WM_TIMER
                '
                static int m, n, cn, nn

                subroutine Clear
                  if n<>cn
                    for x=1 to 5 : SetWindowText(lbl[x])="" : next
                    cn=n
                  endif           
                end subroutine
                '
                mciSendString("status whonext position", temp, 256,0)
                unit=val(temp)
                select unit
                case >= 725 : m=4 : n=30 : KillTimer(hwnd)
                case >= 705 : m=3 : n=29
                case >= 692 : m=2 : n=28
                case >= 682 : m=1 : n=27 : gosub clear   '6'
                case >= 660 : m=4 : n=26
                case >= 636 : m=3 : n=25
                case >= 617 : m=2 : n=24
                case >= 596 : m=1 : n=23 : gosub clear   '5'
                case >= 572 : m=5 : n=22
                case >= 532 : m=4 : n=21
                case >= 510 : m=3 : n=20
                case >= 489 : m=2 : n=19
                case >= 461 : m=1 : n=18 : gosub clear  '4b'
                case >= 422 : m=2 : n=17
                case >= 379 : m=1 : n=16 : gosub clear  '4a'
                case >= 355 : m=5 : n=15
                case >= 336 : m=4 : n=14
                case >= 312 : m=3 : n=13
                case >= 291 : m=2 : n=12
                case >= 265 : m=1 : n=11 : gosub clear  '3'
                case >= 245 : m=5 : n=10
                case >= 228 : m=4 : n=9
                case >= 205 : m=3 : n=8
                case >= 185 : m=2 : n=7
                case >= 165 : m=1 : n=6  : gosub clear  '2'
                case >= 141 : m=5 : n=5
                case >= 121 : m=4 : n=4
                case >= 98  : m=3 : n=3
                case >= 80  : m=2 : n=2
                case >= 59  : m=1 : n=1   '1'
                end select
                '
                if n<>nn
                  SetWindowText(lbl[m],lyrics[n])
                  nn=n
                endif
                '                         
            case WM_CLOSE
                'Close whonext.mid file and sequencer device
                mciSendString("close whonext", 0, 0, 0)
                KillTimer(hwnd)
                DestroyWindow(hwnd)
           
            case WM_DESTROY
                del lyrics
                PostQuitMessage(0)
           
            case else
                return DefWindowProc(hwnd, uMsg, wParam, lParam)
               
        end select
       
        return 0
    end function
     
    'Tom Lehrer - Who's next (1965)
    sub loadlyrics()
    lyrics={
    "First we got the bomb, and that was good,",
    "'Cause we love peace and motherhood.",
    "Then Russia got the bomb, but that's okay,",
    "'Cause the balance of power's maintained that way.",
    "Who's next?",
     
    "Then France got the bomb, but don't you grieve,",
    "'Cause they're on our side (I believe).",
    "China got the bomb, but have no fears,",
    "'Cause they can't wipe us out for a least five years.",
    "Who's next?",
     
    "Japan will have its own device,",
    "Transistorized at half the price.",
    "South Africa wants two, that's right:",
    "One for the black and one for the white.",
    "Who's next?",
     
    "Egypt's gonna get one too,",
    "Just to use on you-know-who.",
    "So Israel's getting tense,",
    "Wants one in self defense.",
    "The Lord's our shepherd says the psalm,",
    "But just in case, we better get a bomb.",
    "Who's next?",
     
    "Luxembourg is next to go,",
    "And (who knows?) maybe Monaco.",
    "We'll try to stay serene and calm",
    "When Alabama gets the bomb.",
    "Who's next?",
    "Who's next?",
    "Who's next?",
    "Who's next??"
    }
    'countof 30
    end sub
     

Roland Stowasser

Thank you Charles for the corrections to WhoNext.o2bas. The source code looks much clearer now than before. The program runs with the last 0.8.0 and the current 0.9.0 distribution. It appears that the 0.9.0 version of Oxygen is stricter and slightly less tolerant when processing commands. I liked the flickering of the lines, it captured the attention and feigned activity. But if this causes problems, this should be avoided.

May I ask why you applied bstring for arry lyrics?  Does this save memory? I always have difficulties to distinguish between string and bstring.