Jose's Read Only Forum 2023

General Category => General Discussion => Topic started by: Patrice Terrier on January 11, 2013, 02:44:59 PM

Title: Get prepared to move on.
Post by: Patrice Terrier on January 11, 2013, 02:44:59 PM
Because it is my intimate conviction that PowerBASIC wouldn't survive to the passing of his creator.

I wonder if, except of BCX, you know some tools that could help translating PB's code to plain C ?

...
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 11, 2013, 05:17:09 PM
Patrice,

The reason for the exclusion of Bcx or are you looking for another alternative?

I am looking for a new home for Bc9 (my bcx port) and hope to have both a new home and an update this month.
In my opinion, although biased , it is the only alternative for what you ask.

James
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 11, 2013, 05:31:06 PM
James

Nothing special against BCX, except that it was unable to convert my PowerBASIC code.
It seems that i have first to convert to the BCX syntax (that is rather different from the current PB's one), and i would avoid the extra step of learning a new syntax.

...
Title: Re: Get prepared to move on.
Post by: Theo Gottwald on January 11, 2013, 10:10:59 PM
Patrice, I have good news for you: Your PB Compiler (while version 10) is still completely alive!
If we talk about newer versions ... thats another topic.
Possibly Steve could say more on this as he has deeper inside knowledge.

Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 11, 2013, 11:20:59 PM
QuoteYour PB Compiler (while version 10) is still completely alive!

No it is not, and i say this because i can make fair comparisons with the other compilers i have already in my toolbox.

Remember the strong debate i had with Bob about a 64-bit version, and now two years later, there is still none... and Bob has passed.

I couldn't see, how Jim who has been at PB for less than 2 years, could take over a problem that Bob himself was not able to solve since so many years.

Indeed i should have moved to C for long, but i was afraid by the amount of work that it would imply to convert my existing PB/DLL code.
And this is the reason why i am looking now for a tool that could help me to move on.

Time for procrastination has passed.

...
Title: Re: Get prepared to move on.
Post by: Israel Vega on January 12, 2013, 03:54:47 AM
I know PowerBASIC source code is designed in TASM.  If there is no 64-bit version of TASM...is possible a new version
of PowerBasic with TASM?.  I ask this to see if the chances of a 64-bit version are real.  Some other compilers (how PureBasic)
are made in FASM...which also compiles to 64 bit.  I would prefer to convert PowerBasic to PureBasic code instead of C. 

Maybe it's time to evolve PowerBasic other platforms where you have no such dependence API'S...

"PureBasic compiles directly to x86, x86-64, PowerPC or 680x0 instruction sets, generating small standalone executables and DLLs which need no runtime libraries beyond the standard system libraries. Programs developed without using the platform-specific application programming interfaces (APIs) can be built easily from the same source file with little or no modification."
http://en.wikipedia.org/wiki/PureBasic (http://en.wikipedia.org/wiki/PureBasic)
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 12, 2013, 10:54:56 AM
 Israel--

PureBasic has the same handicap that PowerBASIC, it is mainly based on the work of a very small (french-german) team, and i would not make twice the same mistake swaping the name of Bob Zale by the name of Frédéric Laboureur.

My problem is not to create work applications (i am using WinDev for that purpose, and so far i neverfound something that could beat its productivity), but to convert my 32-bit DLL to 64-bit without having to retype/convert all the code by hand.

BCX or BC9 (i don't know the difference) could be my solution to perform the conversion, but once i get the job done i will leave PowerBASIC for ever.

I was expecting for a 64-bit PB version, because that would have given me enough time to become fluent with C and perform the transition.

...
Title: To James C. Fuller
Post by: Patrice Terrier on January 12, 2013, 02:28:05 PM
James--

Could you explain what is the difference between BCX and BC9.

I have downloaded BCX, from bcxbasic.99k.org
and also Pelles C, but the documentation looks old and refere to LLC only, not Pelles C.

Could you tell me exactly what is needed to try it.
What are the steps to follow in order to be able to translate current version of PB's code correctly ?

Thank you!
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 12, 2013, 03:02:07 PM
Patrice,
  As of today Bc9 does not have a home but it is in my opinion the best choice.
  Bc9 is my fork of the current Bcx 6.x.x series. The latest BCX 6 series is available only from the BCX Yahoo group.
The original BCX is designed around optional parameters in function calls which is not ansi/iso c compatable.
Lcc and PellesC are the only "c" compilers that can compile the translated source.
That said many c++ compilers can compile the source but SCREAM LOUDLY with many warnings.

I suggest using bc9 with the MinGWTDM compiler suite. Just a -m32 -m64 compile switch for 32/64.
I will try to put together a new package today and post a link here or email you the link.

I just did the Pb HelloWin.bas -> bc9

You also should decide early on if you want need c++. c and c++ are two distinct different languages and many things
work differently.

James


PowerBASIC HelloWin.bas

'==============================================================================
'
'   HELLOWIN.BAS for PowerBASIC for Windows
'   Copyright (c) 1997-2011 PowerBASIC, Inc.
'   All Rights Reserved.
'
'   Translation of HELLOWIN.C from Charles Petzold's book:
'
'     "Programming Windows 95" published by Microsoft Press.
'     ISBN 1-55615-676-6
'
'   Note: The original code does not contain the "gradient" effect.
'
'==============================================================================

#COMPILER PBWIN 10
#COMPILE EXE
#DIM ALL

#INCLUDE ONCE "Win32API.inc"

#RESOURCE RES, "HelloWin.res"     ' this gives the program the "hellowin" icon


'==============================================================================
FUNCTION WINMAIN (BYVAL hInstance     AS DWORD, _
                  BYVAL hPrevInstance AS DWORD, _
                  BYVAL lpCmdLine     AS ASCIIZ PTR, _
                  BYVAL iCmdShow      AS LONG) AS LONG
'------------------------------------------------------------------------------
    ' Program entry point
    '--------------------------------------------------------------------------

    LOCAL Msg       AS tagMsg
    LOCAL wce       AS WndClassEx
    LOCAL szAppName AS ASCIIZ * 80
    LOCAL hWnd      AS DWORD

    ' Setup and register a window class for the main window
    ' CODEPTR is used to pass the address of the function that will
    ' receive all messages sent to any window created with this class
    szAppName         = "HelloWin"
    wce.cbSize        = SIZEOF(wce)
    wce.STYLE         = %CS_HREDRAW OR %CS_VREDRAW
    wce.lpfnWndProc   = CODEPTR(WndProc)
    wce.cbClsExtra    = 0
    wce.cbWndExtra    = 0
    wce.hInstance     = hInstance
    wce.hIcon         = LoadIcon(hInstance, "HELLOWIN")
    wce.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
    wce.hbrBackground = %NULL ' No class background, we do it outselves
    wce.lpszMenuName  = %NULL
    wce.lpszClassName = VARPTR(szAppName)
'    wce.hIconSm       = LoadIcon(hInstance, BYVAL %IDI_APPLICATION)

    RegisterClassEx wce

    ' Create a window using the registered class
    hWnd = CreateWindow(szAppName, _               ' window class name
                        "The Hello Program", _     ' window caption
                        %WS_OVERLAPPEDWINDOW, _    ' window style
                        %CW_USEDEFAULT, _          ' initial x position
                        %CW_USEDEFAULT, _          ' initial y position
                        %CW_USEDEFAULT, _          ' initial x size
                        %CW_USEDEFAULT, _          ' initial y size
                        %NULL, _                   ' parent window handle
                        %NULL, _                   ' window menu handle
                        hInstance, _               ' program instance handle
                        BYVAL %NULL)               ' creation parameters

    IF hWnd = 0 THEN  ' exit on failure
        MSGBOX "Unable to create window"
        EXIT FUNCTION
    END IF

    ' Display the window on the screen
    ShowWindow hWnd, iCmdShow
    UpdateWindow hWnd

    ' Main message loop:
    ' Messages sent to HELLOWIN while it has the focus are received by
    ' GetMessage().  This loop translates each message and dispatches it
    ' to the appropriate handler.  When PostQuitMessage() is called, the
    ' loop terminates which ends the application.
    DO WHILE GetMessage(Msg, %NULL, 0, 0)
        TranslateMessage Msg
        DispatchMessage Msg
    LOOP

    FUNCTION = msg.wParam

END FUNCTION


'==============================================================================
SUB DrawGradient (BYVAL hDC AS DWORD)
'------------------------------------------------------------------------------
    ' Custom draw procedure for gradiend fill
    '--------------------------------------------------------------------------

    LOCAL rectFill AS RECT
    LOCAL rectClient AS RECT
    LOCAL fStep AS SINGLE
    LOCAL hBrush AS DWORD
    LOCAL lOnBand AS LONG

    GetClientRect WindowFromDC(hDC), rectClient
    fStep = rectClient.nbottom / 200

    FOR lOnBand = 0 TO 199
        SetRect rectFill, 0, lOnBand * fStep, rectClient.nright + 1, (lOnBand + 1) * fStep
        hBrush = CreateSolidBrush(RGB(0, 0, 255 - lOnBand))
        Fillrect hDC, rectFill, hBrush
        DeleteObject hBrush
    NEXT

END SUB


'==============================================================================
FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
                  BYVAL wParam AS DWORD, BYVAL lParam AS LONG) EXPORT AS LONG
'------------------------------------------------------------------------------
    ' WndProc is the message handler for all windows creating using the HelloWin
    ' class name.  A single WndProc procedure can handle multiple windows by
    ' testing the hWnd variable passed to it.
    '--------------------------------------------------------------------------

    LOCAL hDC    AS DWORD
    LOCAL pPaint AS PAINTSTRUCT
    LOCAL tRect  AS RECT

    ' The SELECT CASE is used to catch only those messages which the message
    ' handler needs to process.  All other messages are passed through the
    ' tests to the default handler.
    SELECT CASE wMsg

    CASE %WM_CREATE

    CASE %WM_PAINT
        hDC = BeginPaint(hWnd, pPaint)
        GetClientRect hWnd, tRect
        SetBkMode hDC, %TRANSPARENT
        SetTextColor hDC, %WHITE
        DrawText hDC, "Hello, Windows!", -1, tRect, %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER
        EndPaint hWnd, pPaint
        FUNCTION = 1
        EXIT FUNCTION

    CASE %WM_ERASEBKGND
        hDC = wParam
        DrawGradient hDC              ' Pass the DC of the region to repaint
        FUNCTION = 1
        EXIT FUNCTION

    CASE %WM_DESTROY
        PostQuitMessage 0
        EXIT FUNCTION

    END SELECT

    ' Any message which is not handled in the above SELECT CASE reaches this
    ' point and is processed by the Windows default message handler.
    FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION




Bc9 HelloWin,bas


'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Translation of PowerBASIC SDK example HelloWin
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

'Batch file for compiling
$ONEXIT "GWGCCW.BAT $FILE$ -m64 gui"

FUNCTION WINMAIN()
    DIM Msg         As MSG
    Dim wce           AS WNDCLASSEX
    Dim szAppName[80] As char     
    Dim hWnd          AS HWND
   
    szAppName$ = "HelloWin"
   
    wce.cbSize        = SIZEOF(wce)
    wce.style         = CS_HREDRAW OR CS_VREDRAW
    wce.lpfnWndProc   = WndProc
    wce.cbClsExtra    = 0
    wce.cbWndExtra    = 0
    wce.hInstance     = hInst
    wce.hIcon         = LoadIcon(hInst, "HELLOWIN")
    wce.hCursor       = LoadCursor(NULL, IDC_ARROW)
    wce.hbrBackground = NULL
    wce.lpszMenuName  = NULL
    wce.lpszClassName = szAppName$

    If RegisterClassEx(&wce) = 0 Then
        MsgBox "RegisterClass failed"
        Exit Function
    End If
   
    ' Create a window using the registered class
    hWnd = CreateWindow(szAppName$, _               ' window class name
                        "The Hello Program", _     ' window caption
                        WS_OVERLAPPEDWINDOW, _    ' window style
                        CW_USEDEFAULT, _          ' initial x position
                        CW_USEDEFAULT, _          ' initial y position
                        CW_USEDEFAULT, _          ' initial x size
                        CW_USEDEFAULT, _          ' initial y size
                        NULL, _                   ' parent window handle
                        NULL, _                   ' window menu handle
                        hInst, _               ' program instance handle
                        NULL)               ' creation parameters
   
    IF hWnd = 0 THEN  ' exit on failure
        MSGBOX "Unable to create window"
        EXIT FUNCTION
    END IF
   
    ' Display the window on the screen
    ShowWindow(hWnd, CmdShow)
    UpdateWindow(hWnd)

    ' Main message loop:
    ' Messages sent to HELLOWIN while it has the focus are received by
    ' GetMessage().  This loop translates each message and dispatches it
    ' to the appropriate handler.  When PostQuitMessage() is called, the
    ' loop terminates which ends the application.
    DO WHILE GetMessage(&Msg, NULL, 0, 0)
        TranslateMessage(&Msg)
        DispatchMessage(&Msg)
    LOOP
   
   

    Function = Msg.wParam
End Function
'==============================================================================
SUB DrawGradient (hDC AS HDC)
'------------------------------------------------------------------------------
    ' Custom draw procedure for gradiend fill
    '--------------------------------------------------------------------------

    Dim rectFill AS RECT
    Dim rectClient AS RECT
    Dim fStep AS SINGLE
    Dim hBrush AS HBRUSH
    Dim lOnBand AS int

    GetClientRect(WindowFromDC(hDC), &rectClient)
   
    fStep = rectClient.bottom / 200

    FOR lOnBand = 0 TO 199
        SetRect(&rectFill, 0, lOnBand * fStep, rectClient.right + 1, (lOnBand + 1) * fStep)
        hBrush = CreateSolidBrush(RGB(0, 0, 255 - lOnBand))
        FillRect( hDC, &rectFill, hBrush)
        DeleteObject( hBrush)
    NEXT

END SUB

'==============================================================================
CALLBACK FUNCTION WndProc()
'------------------------------------------------------------------------------
    ' WndProc is the message handler for all windows creating using the HelloWin
    ' class name.  A single WndProc procedure can handle multiple windows by
    ' testing the hWnd variable passed to it.
    '--------------------------------------------------------------------------

    Raw hDC    AS HDC
    Raw pPaint AS PAINTSTRUCT
    Raw tRect  AS RECT

    ' The SELECT CASE is used to catch only those messages which the message
    ' handler needs to process.  All other messages are passed through the
    ' tests to the default handler.
    Select Case CBMSG
        Case WM_PAINT
            hDC = BeginPaint(CBHNDL, &pPaint)
            GetClientRect(CBHNDL, &tRect)
            SetBkMode(hDC, TRANSPARENT)
            SetTextColor(hDC, RGB(255,255,255))
            DrawText(hDC, "Hello, Windows!", -1, &tRect, DT_SINGLELINE OR DT_CENTER OR DT_VCENTER)
            EndPaint(hWnd, &pPaint)
            FUNCTION = 1
        Case WM_ERASEBKGND
            hDC = (HDC)wParam
            DrawGradient(hDC)              ' Pass the DC of the region to repaint
            FUNCTION = 1
         Case WM_DESTROY
             PostQuitMessage(0)
    End Select
   
End Function

Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 12, 2013, 03:07:55 PM
Here is the "c" code


// *********************************************************************
// Created with bc9 - BASIC To C/C++ Translator (V) 9.1.0.3 (2013/1/10)
//                 BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
//          Translated for compiling with an ANSI/ISO C Compiler
//                           On MS Windows
// *********************************************************************
#include <windows.h>    // Win32 Header File
#include <windowsx.h>   // Win32 Header File
#include <commctrl.h>   // Win32 Header File
#include <commdlg.h>    // Win32 Header File
#include <mmsystem.h>   // Win32 Header File
#include <shellapi.h>   // Win32 Header File
#include <shlobj.h>     // Win32 Header File
#include <richedit.h>   // Win32 Header File
#include <wchar.h>      // Win32 Header File
#include <objbase.h>    // Win32 Header File
#include <ocidl.h>      // Win32 Header File
#include <winuser.h>    // Win32 Header File
#include <olectl.h>     // Win32 Header File
#include <oaidl.h>      // Win32 Header File
#include <ole2.h>       // Win32 Header File
#include <oleauto.h>    // Win32 Header File
#include <winsock.h>    // Win32 Header File
#include <process.h>    // dos
#include <conio.h>      // dos
#include <direct.h>     // dos
#include <io.h>         // dos
#include <ctype.h>      // dos/linux
#include <fcntl.h>      // dos/linux
#include <math.h>       // dos/linux
#include <stdio.h>      // dos/linux
#include <string.h>     // dos/linux
#include <stddef.h>     // dos/linux
#include <stdlib.h>     // dos/linux
#include <setjmp.h>     // dos/linux
#include <time.h>       // dos/linux
#include <stdarg.h>     // dos/linux
#include <sys/types.h> 
#include <sys/stat.h>   


// *************************************************
//        User's GLOBAL ENUM blocks
// *************************************************

// *************************************************
//            System Defined Constants
// *************************************************

#define CCPTR const char*
#define cSizeOfDefaultString 2048

// *************************************************
//            User Defined Constants
// *************************************************


// *************************************************
//               Standard Prototypes
// *************************************************

// char*   BCX_TmpStr(size_t,size_t= 128,int= 1);
char*    BCX_TmpStr( size_t,size_t,int);
// char*   command (int=-1);
char*    command( int);
// *************************************************
//          User Defined Types And Unions
// *************************************************


// *************************************************
//                System Variables
// *************************************************

static char    SPC [2]={32,0};  /* Space */

// *************************************************
//            User Global Variables
// *************************************************

static PCHAR   *g_argv;
static int     g_argc;


// *************************************************
//               Standard Macros
// *************************************************

#define BOR |


// *************************************************
//               User Prototypes
// *************************************************

int     WINAPI WinMain (HINSTANCE,HINSTANCE,LPSTR,int);
void    DrawGradient (HDC);
LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);
void    DoCmdLine (void);

// *************************************************
//            User Global Initialized Arrays
// *************************************************



// *************************************************
//                 Runtime Functions
// *************************************************

#ifndef BCXTmpStrSize
#define BCXTmpStrSize  2048
#endif
char *BCX_TmpStr (size_t Bites,size_t  iPad,int iAlloc)
{
  static int   StrCnt;
  static char *StrFunc[BCXTmpStrSize];
  StrCnt=(StrCnt + 1) & (BCXTmpStrSize-1);
  if(StrFunc[StrCnt]) {free (StrFunc[StrCnt]); StrFunc[StrCnt] = NULL;}
#if defined BCX_MAX_VAR_SIZE
  if(Bites*sizeof(char)>BCX_MAX_VAR_SIZE)
  {
  printf("Buffer Overflow caught in BCX_TmpStr - requested space of %d EXCEEDS %d\n",(int)(Bites*sizeof(char)),BCX_MAX_VAR_SIZE);
  abort();
  }
#endif
  if(iAlloc) StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
  return StrFunc[StrCnt];
}


char *command (int nArg)
{
register int i = 0;
char *c = 0, *retstr, *s = GetCommandLine();
if(nArg < i) // return entire commandline
    {
    while(*s && *s != 32) {
      if(*s == 34) while(*++s && *s != 34);
      s++;
      }
    while(isspace((unsigned char)*s))s++;
    retstr = BCX_TmpStr(strlen(s)+1,128,1);
    strcpy(retstr, s);
    if(*(retstr+strlen(retstr)-1)==20) *retstr=0;
    return retstr;
    }
  while(i <= nArg) {
    while(isspace((unsigned char)*s)) s++; // skip whitespace
    c = s;
    if(*s == 34) {                           // argument starts a quote
      while(*++s && *s != 34);          // skip till next quote
        if(*s) s++;                       // skip quote itself
    }
    else {
      while(*s && *s != 32) s++;
     }
    i++;
    }
  if(*c == 34) {
      c++;                                 // skip leading quote
      if(*(s-1) == 34) s--;                // skip any trailing quotes
    }
  retstr = BCX_TmpStr((s - c) + 1,128,1);
  strncpy(retstr, c, (s - c));
  retstr[s-c]=0;
  return retstr;
}



// ************************************
//       User Subs and Functions
// ************************************

int WINAPI WinMain (HINSTANCE hInst,HINSTANCE hPrev,LPSTR CmdLine,int CmdShow)
{
  static MSG      Msg;
  memset(&Msg,0,sizeof(Msg));
  static WNDCLASSEX  wce;
  memset(&wce,0,sizeof(wce));
  static char     szAppName[80];
  memset(&szAppName,0,sizeof(szAppName));
  static HWND     hWnd;
  memset(&hWnd,0,sizeof(hWnd));
  strcpy(szAppName,"HelloWin");
  wce.cbSize= sizeof( wce);
  wce.style= CS_HREDRAW  BOR  CS_VREDRAW;
  wce.lpfnWndProc= WndProc;
  wce.cbClsExtra= 0;
  wce.cbWndExtra= 0;
  wce.hInstance= hInst;
  wce.hIcon= LoadIcon( hInst,"HELLOWIN");
  wce.hCursor= LoadCursor( NULL, IDC_ARROW);
  wce.hbrBackground= NULL;
  wce.lpszMenuName= NULL;
  wce.lpszClassName= szAppName;
  if(RegisterClassEx( &wce)==0 )
    {
      MessageBox (GetActiveWindow(),"RegisterClass failed","",0);
      return 0;
    }
  hWnd= CreateWindow( szAppName,"The Hello Program", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,(HMENU) NULL, hInst, NULL);
  if(hWnd==0 )
    {
      MessageBox (GetActiveWindow(),"Unable to create window","",0);
      return 0;
    }
  ShowWindow(hWnd,CmdShow);
  UpdateWindow(hWnd);
  while(GetMessage( &Msg,NULL,0,0))
    {
      TranslateMessage( &Msg);
      DispatchMessage( &Msg);
    }

  return Msg.wParam;
}


void DrawGradient (HDC hDC)
{
  static RECT     rectFill;
  memset(&rectFill,0,sizeof(rectFill));
  static RECT     rectClient;
  memset(&rectClient,0,sizeof(rectClient));
  static float    fStep;
  memset(&fStep,0,sizeof(fStep));
  static HBRUSH   hBrush;
  memset(&hBrush,0,sizeof(hBrush));
  static int      lOnBand;
  memset(&lOnBand,0,sizeof(lOnBand));
  GetClientRect(WindowFromDC(hDC), &rectClient);
  fStep= rectClient.bottom/ 200;
  for(lOnBand=0; lOnBand<=199; lOnBand+=1)
    {
      SetRect( &rectFill,0,lOnBand*fStep,rectClient.right+1,(lOnBand+1)*fStep);
      hBrush= CreateSolidBrush( RGB( 0, 0, 255- lOnBand));
      FillRect(hDC, &rectFill,hBrush);
      DeleteObject(hBrush);
    }

}


LRESULT CALLBACK WndProc (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
  HDC      hDC;
  PAINTSTRUCT  pPaint;
  RECT     tRect;
  if(Msg==WM_PAINT )
    {
      hDC= BeginPaint( hWnd,  &pPaint);
      GetClientRect(hWnd, &tRect);
      SetBkMode(hDC,TRANSPARENT);
      SetTextColor(hDC,RGB(255,255,255));
      DrawText(hDC,"Hello, Windows!",-1, &tRect,DT_SINGLELINE  BOR  DT_CENTER  BOR  DT_VCENTER);
      EndPaint(hWnd, &pPaint);
      return 1;
    }
  if(Msg==WM_ERASEBKGND )
    {
      hDC=( HDC) wParam;
      DrawGradient(hDC);
      return 1;
    }
  if(Msg==WM_DESTROY )
    {
      PostQuitMessage(0);
    }
  return DefWindowProc(hWnd, Msg, wParam, lParam); // CallBackFlag
}


void DoCmdLine (void)
{
  int      i=0;
  static char    cmd[32][cSizeOfDefaultString];
  static char*    argv[32];
  strcpy(cmd[0],SPC);
  for(;;)
    {
      if(strlen(command(i)))
        {
          strcpy(cmd[i],command(i));
          argv[i]  =( char*) cmd[ i];
        }
      else
        {
          goto L1003;
        }
      i++;
    }
L1003:;
  g_argc= i;
  g_argv= argv;
}



Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 12, 2013, 04:08:20 PM
James--

Can i use VS 2010 Pro with BC9 ?

IF Answer = YES THEN
    How to setup BC9 for VS 2010
ELSE
    How to setup BC9 for MinGWTDM
END IF

Could you provide a detailed check list of everything needed to use BC9, including the batch file to produce either 32-bit or 64-bit from prompt.

QuoteI will try to put together a new package today and post a link here or email you the link.
Either way, would be nice, thank you!

...
Title: BC9 / PB syntax differences
Post by: Patrice Terrier on January 12, 2013, 04:39:26 PM
James --

It looks like BC9 is not 100% compatible with the current PB's syntax, implying that we have to edit first the PB's code?

For example we have to use DIM instead of LOCAL, and we can't have is list of common declarations onto the same line.
It understands only DDT CBMSG in the windproc instead of plain SDK syntax, and we have to add the "CALLBACK" reserved word in front of each callback.

Do you know if there is a complete list of all the differences ?

With such a list, i could write a utility to convert first my PB's code to the the BC9 syntax that seems to match only the ten years old PB's syntax.

...
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 12, 2013, 05:37:22 PM
Patrice,
  Of course bc9 is not 100% compatible, but I doubt you'll find anything closer.
The package includes the RadAsm3 ide configured for bc9/BCX with all the batch files and instructions on it's
operation.

  I got a bit carried away with the shortcuts. One of the best aspects of Bc9 is it's versitility.
This is also quite acceptable:


'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Translation of PowerBASIC SDK example HelloWin
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

'Batch file for compiling
$ONEXIT "GWGCCW.BAT $FILE$ -m64 gui"

FUNCTION WINMAIN(hInst AS HINSTANCE,hPrev AS HINSTANCE,CmdLine As LPSTR,CmdShow AS Integer) As Integer
    LOCAL Msg         As MSG
    LOCAL wce           AS WNDCLASSEX
    LOCAL szAppName[80] As char     
    LOCAL hWnd          AS HWND
   
    szAppName$ = "HelloWin"
   
    wce.cbSize        = SIZEOF(wce)
    wce.style         = CS_HREDRAW OR CS_VREDRAW
    wce.lpfnWndProc   = WndProc
    wce.cbClsExtra    = 0
    wce.cbWndExtra    = 0
    wce.hInstance     = hInst
    wce.hIcon         = LoadIcon(hInst, "HELLOWIN")
    wce.hCursor       = LoadCursor(NULL, IDC_ARROW)
    wce.hbrBackground = NULL
    wce.lpszMenuName  = NULL
    wce.lpszClassName = szAppName$

    If RegisterClassEx(&wce) = 0 Then
        MsgBox "RegisterClass failed"
        Exit Function
    End If
   
    ' Create a window using the registered class
    hWnd = CreateWindow(szAppName$, _               ' window class name
                        "The Hello Program", _     ' window caption
                        WS_OVERLAPPEDWINDOW, _    ' window style
                        CW_USEDEFAULT, _          ' initial x position
                        CW_USEDEFAULT, _          ' initial y position
                        CW_USEDEFAULT, _          ' initial x size
                        CW_USEDEFAULT, _          ' initial y size
                        NULL, _                   ' parent window handle
                        NULL, _                   ' window menu handle
                        hInst, _               ' program instance handle
                        NULL)               ' creation parameters
   
    IF hWnd = 0 THEN  ' exit on failure
        MSGBOX "Unable to create window"
        EXIT FUNCTION
    END IF
   
    ' Display the window on the screen
    ShowWindow(hWnd, CmdShow)
    UpdateWindow(hWnd)

    ' Main message loop:
    ' Messages sent to HELLOWIN while it has the focus are received by
    ' GetMessage().  This loop translates each message and dispatches it
    ' to the appropriate handler.  When PostQuitMessage() is called, the
    ' loop terminates which ends the application.
    DO WHILE GetMessage(&Msg, NULL, 0, 0)
        TranslateMessage(&Msg)
        DispatchMessage(&Msg)
    LOOP
   
   

    Function = Msg.wParam
End Function
'==============================================================================
SUB DrawGradient (hDC AS HDC)
'------------------------------------------------------------------------------
    ' Custom draw procedure for gradiend fill
    '--------------------------------------------------------------------------

    LOCAL rectFill AS RECT
    LOCAL rectClient AS RECT
    LOCAL fStep AS SINGLE
    LOCAL hBrush AS HBRUSH
    LOCAL lOnBand AS int

    GetClientRect(WindowFromDC(hDC), &rectClient)
   
    fStep = rectClient.bottom / 200

    FOR lOnBand = 0 TO 199
        SetRect(&rectFill, 0, lOnBand * fStep, rectClient.right + 1, (lOnBand + 1) * fStep)
        hBrush = CreateSolidBrush(RGB(0, 0, 255 - lOnBand))
        FillRect( hDC, &rectFill, hBrush)
        DeleteObject( hBrush)
    NEXT

END SUB

'==============================================================================
FUNCTION WndProc (hWnd AS HWND, Msg AS UINT, wParam AS WPARAM, lParam AS LPARAM) AS LRESULT

'------------------------------------------------------------------------------
    ' WndProc is the message handler for all windows creating using the HelloWin
    ' class name.  A single WndProc procedure can handle multiple windows by
    ' testing the hWnd variable passed to it.
    '--------------------------------------------------------------------------

    LOCAL hDC    AS HDC
    LOCAL pPaint AS PAINTSTRUCT
    LOCAL tRect  AS RECT

    ' The SELECT CASE is used to catch only those messages which the message
    ' handler needs to process.  All other messages are passed through the
    ' tests to the default handler.
    Select Case Msg
        Case WM_PAINT
            hDC = BeginPaint(hWnd, &pPaint)
            GetClientRect(hWnd, &tRect)
            SetBkMode(hDC, TRANSPARENT)
            SetTextColor(hDC, RGB(255,255,255))
            DrawText(hDC, "Hello, Windows!", -1, &tRect, DT_SINGLELINE OR DT_CENTER OR DT_VCENTER)
            EndPaint(hWnd, &pPaint)
            FUNCTION = 1
        Case WM_ERASEBKGND
            hDC = (HDC)wParam
            DrawGradient(hDC)              ' Pass the DC of the region to repaint
            FUNCTION = 1
         Case WM_DESTROY
             PostQuitMessage(0)
    End Select
    Function = DefWindowProc(hWnd, Msg, wParam, lParam)
End Function


One thing to note: I don't know whhat Pb does when a variable is defined as LOCAL.
This is what Bc9 does.


  static MSG      Msg;
  memset(&Msg,0,sizeof(Msg));
  static WNDCLASSEX  wce;
  memset(&wce,0,sizeof(wce));
  static char     szAppName[80];
  memset(&szAppName,0,sizeof(szAppName));
  static HWND     hWnd;
  memset(&hWnd,0,sizeof(hWnd));


Also I assume you realize all parameters in c/bcx are the exact opposite of PowerBASIC. Default is byval to pass by ref
you use the ampersand &myvar


A list of all the differences?? No. never needed one.


James
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 12, 2013, 06:58:14 PM
James--

Link to small Test.bas DLL has been sent to you, because your gmail account does not accept zip attachment.

Thank you!
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 12, 2013, 08:48:43 PM
Patrice,
  Update.
  I commented out all the 32bit dll declarations and it still compiled fine with PB so I assume they were not needed?
The other item is the bass.dll. Is there a 64bit version of it?

James
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 12, 2013, 11:17:19 PM
I found there is a 64bit version of bass.dll.

I am working my way through the code and I am learning much.

BYVAL / BYREF are supported so a lot less editing

James
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 13, 2013, 09:56:28 AM
James--

Yes, there is a 64-bit version of Bass.dll (but so far i have not translated the header to 64-bit yet)
If BC9 is able to convert the existing PB's code correctly to 32-bit C (VS 2010), then that would be already a good step forward and i think i could start from there.

...
Title: Re: Get prepared to move on.
Post by: Marc Pons on January 13, 2013, 01:26:10 PM
Hy James

I am also interrested in BC9 , I tested some months ago using BCX with pelleC but the results where not very efficient.

May you post your software here , I've tried in the BCX forum, I was thinking it could be there, but I can't register.

Thank's,  Marc
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 13, 2013, 05:22:54 PM
I am still working on a few issues for a new release.
I don't think a PowerBASIC board would be a place for such a package.

One thing that is mandatory for converting PB code to Bc9: Your PowerBASIC code must have #DIM ALL !

I will keep you updated here.

James
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 13, 2013, 05:59:22 PM
James,

This section is not an exclusive PowerBASIC board, you can speak of any programming language or translator here.  ;D

...
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 13, 2013, 06:44:08 PM

While I look for a new home for bc9 would it be appropriate  to attach the package to a message here?
It's about 8000KB in rar format. 4400KB 7z but it appears that is not allowed.

James
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 13, 2013, 07:54:42 PM
Perhaps you could you split it into two or three parts.

Then i would rebuild the whole package into one single ZIP file, and host it on my web-site,
then i could post a link here to download the full zip file for those who want it.

...
Title: BCX compatibility
Post by: Patrice Terrier on January 13, 2013, 07:58:12 PM
QuoteHi Patrice,

In my experience, PB SDK style coding converted fairly well 70% - 80% with most issues being solved using search & replace in your favorite editor.

I haven't done much since PB 8.x, so I don't know how true that holds for PB9 /PB10.


Also, I only use BCX 6.22 (with a few personal modifications), so I don't can't say what issues you might experience with any of the newer variations of BCX.

My hunch is that for large blocks of code, BCX can do much of the translation pretty well but you should expect to have to do some editing of the translated code.


Hope that helps -- GOOD LUCK!

Kevin
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 13, 2013, 08:07:53 PM
Patrice,
  It states that max attachment per msg here is 12000KB so, unless there is a problem with hosting it here, it appears it is well under the max size???

James
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 13, 2013, 09:41:37 PM
One thing to note and decide is if you want to ignore warnings.

Example.
This compiles fine but if warnings are on you'll get a warning on this code.

Pb and Bc9 code is the same

SUB SyncProc(BYVAL nSync AS LONG, BYVAL nChannel AS DWORD, BYVAL nData AS LONG, BYVAL nUser AS DWORD)
    LOCAL nRet AS LONG
    nRet = ChannelSetPosition(nChannel, gnPos, 0)
    IF nSync = gnLastSync AND WM_BASSSYNC THEN PostMessage(nUser, WM_BASSSYNC, 0, 0)
END SUB


translation

void SyncProc (long nSync,DWORD nChannel,long nData,DWORD nUser)
{
  static long     nRet;
  memset(&nRet,0,sizeof(nRet));
  nRet= ChannelSetPosition( nChannel, gnPos, 0);
  if(nSync==gnLastSync&&WM_BASSSYNC )
    {
      PostMessage(nUser,WM_BASSSYNC,0,0);
    }
}



warning: passing argument 1 of 'PostMessageA' makes pointer from integer without a cast [enabled by default]

gcc wants nUser to be of type HWND

The warning actually tells you what it wants so you don't have to go look it up.

note: expected 'HWND' but argument is of type 'DWORD'


James
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 14, 2013, 03:44:04 AM
interesting read on the 'Unreasonable Effectiveness Of C' ...

http://damienkatz.net/2013/01/the_unreasonable_effectiveness_of_c.html

fred
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 14, 2013, 03:55:34 AM
Quote
I got a bit carried away with the shortcuts. One of the best aspects of Bc9 is it's versitility.
This is also quite acceptable:



I'm glad you posted that James.  I was studying your examples, and couldn't imagine what happened to the parameters to WinMain() and WndProc() in the BC9 version!
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 14, 2013, 10:26:24 AM
James--

I do not agree with the translation of the PowerBASIC LOCAL keyword, into C static

In PowerBASIC, Local variables retain their values only until the end of the procedure.

In C, when you declare a variable in a function, the static keyword specifies that the variable retains its state between calls to that function. It means it is exatly the same than using the STATIC powerBASIC keyword.

However in C, when you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or funcion has internal linkage. Whe you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.

See below the use of the static keyword outside procedure or function to mimic a string constant:// GDImage.cpp : définit les fonctions exportées pour l'application DLL.
//
#include <windows.h>
#include <iostream>
#include <string.h>

#include "stdafx.h"
#include "GDImage.h"

typedef struct {
HWND    hWnd;
LONG anchor;
RECT rc;
LONG TiledBitmap;
CHAR order[METADATA_SIZE];
LONG ordersize;
LONG WMBit[25];
DWORD WMCodePtr[25 * 32];
LONG centerx;
LONG centery;
LONG Composited;
} ZIMAGEPROP;

static char *Version = "6.06";

/* Add two integers */
//_declspec (dllexport) long add_num(long a, long b){
//     return((long)(a+b));}
long add_num(long a, long b){
     return((long)(a + b));}

char* ZI_Version () {
    return Version; // Version number of the form "#.#"
}


Indeed, inside the SyncProc procedure
PB: LOCAL nRet AS LONG
should be just translated to
C: long nRet (without the static keyword)

...
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 14, 2013, 10:36:49 AM
Fred,

I totaly agree with Damien Katz, for a SDK coder like myself, C it is the only manageable way to replace my existing PB's SDK code, to keep producing small, fast, and runtime free DLLs.

...
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 14, 2013, 01:47:58 PM
Patrice,
  In actuality LOCAL in bc9 works the same as PowerBASIC. Why the static I don't know but the results are the
same although the initialization each time the function is called is overhead that might want to be considered.
Note the AS type may also follow the var as in:
  Raw I2 As Integer

From the help file:
A variable dimensioned with DIM or LOCAL in a subroutine or function retains the value on exit,
but will lose it on re-entry due to the automatic initialization.
James

This bc9 line

LOCAL AS Integer I1


produces this c code


  static int      I1;
  memset(&I1,0,sizeof(I1));


These are 4 different ways to declare variables.
here is bc9 sample code

'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Test LOCAL,RAW
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

$NOMAIN
$ONEXIT "GWGCC.BAT $FILE$ -m32 con"
Sub DoTest()
    LOCAL AS Integer I1
    RAW AS Integer I2
    Raw As Integer I3=0
    STATIC As Integer I4
   
    Print "I1 = ", I1
    PRINT "I2 = ", I2
    PRINT "I3 = ", I3
    PRINT "I4 = ", I4
    PRINT "----------"
    I1 = 1
    I2 = 2
    I3 = 3
    I4++
    PRINT "I1 = ", I1
    PRINT "I2 = ", I2
    PRINT "I3 = ", I3
    PRINT "I4 = ", I4       
End Function
'==============================================================================
Function main(argc As Integer,argv As PCHAR ptr ) As Integer
Raw As Integer i

For i = 1 To 3
    DoTest()
    PRINT "********"
Next
Pause
End Function



c translation:

SNIP

void DoTest (void)
{
  static int      I1;
  memset(&I1,0,sizeof(I1));
  int      I2;
  int      I3=0;
  static int      I4;
  printf("%s% d\n","I1 = ",(int)I1);
  printf("%s% d\n","I2 = ",(int)I2);
  printf("%s% d\n","I3 = ",(int)I3);
  printf("%s% d\n","I4 = ",(int)I4);
  printf("%s\n","----------");
  I1= 1;
  I2= 2;
  I3= 3;
  I4++;
  printf("%s% d\n","I1 = ",(int)I1);
  printf("%s% d\n","I2 = ",(int)I2);
  printf("%s% d\n","I3 = ",(int)I3);
  printf("%s% d\n","I4 = ",(int)I4);
}


int main (int argc,PCHAR* argv)
{
  int      i;
  for(i=1; i<=3; i+=1)
    {
      DoTest();
      printf("%s\n","********");
    }

  Pause();
  return 0;
}



and the output:

I1 =  0
I2 =  0
I3 =  0
I4 =  0
----------
I1 =  1
I2 =  2
I3 =  3
I4 =  1
********
I1 =  0
I2 =  0
I3 =  0
I4 =  1
----------
I1 =  1
I2 =  2
I3 =  3
I4 =  2
********
I1 =  0
I2 =  0
I3 =  0
I4 =  2
----------
I1 =  1
I2 =  2
I3 =  3
I4 =  3
********
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 15, 2013, 07:36:34 PM
I have started to work on the translation of my GDImage.dll to plain C 64-bit by hand, because BCX is absolutly not reliable, what a slow process !!!

:(
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 15, 2013, 08:16:16 PM
Patrice,
What compiler are you using for your plain c? I ask because VC++ is only c(89) for "c" code.

James

Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 15, 2013, 08:49:12 PM
Are you planning to use C or C++ compilation Patrice?  Just my opinion, but I prefer greatly using the *.cpp file extension, and using therefore C++ compilation.  In that way, without going into all the nastiness of C++ (STL being the biggies), one gets some significant advantages. 

I never fully embraced everything in C++; but prefer compiling as C++, even though my coding style is mostly C centric (whatever that means).
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 16, 2013, 09:50:57 AM
I am using Microsoft Visual Studio 2010 Professional.

Here is my config type:
- Create Dynamic library (.dll)
- Use Windows standard library
- Do not use ATL
- Use Unicode
- Do not use the Common Language Runtime

Command line:
/Zi /nologo /W3 /WX- /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "GDIMAGE_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Yu"StdAfx.h" /Fp"x64\Release\GDImage.pch" /Fa"x64\Release\" /Fo"x64\Release\" /Fd"x64\Release\vc100.pdb" /Gz /errorReport:queue

Note: I am using /Gz (__stdcall)
source code has the .cpp extension.

Here is an example of the header i am using (work in progress)//#define       METADATA_SIZE    2048
const int       METADATA_SIZE       = 2048;
//const char    *GDImageClassName   = "ZIMAGECTRL";
const wchar_t   *GDImageClassName   = L"ZIMAGECTRL";
const wchar_t   *GLImageClassName   = L"ZOPENGLCTRL";

// See below the list of GDImage properties:
// Note: Constants prefixed with %ZI_ are for IMAGE control
const int ZI_DC                 = 1;    // Internal DC
const int ZI_Bitmap             = 2;    // Memory Bitmap
const int ZI_Horizontal         = 3;    // Horizontal scrolling position
const int ZI_Vertical           = 4;    // Vertical scrolling position
const int ZI_GradientTop        = 5;    // Top gradiant color backgroud
const int ZI_GradientBottom     = 6;    // Bottom gradiant color backgroud

const int ZI_FitToWindow        = 7;    // Resize the image to fit the view port
const int    ZI_QualityDefault  = -1;   // And use any of this constant as Parameter
const int    ZI_QualityGood     = 1;    // Best performance
const int    ZI_QualityHigh     = 2;    // Best rendering quality
// DO NOT use or alter these properties!
const int ZI_PaintDC            = 8;    // Internal DC
const int ZI_PaintBitmap        = 9;    // Memory Bitmap
const int ZI_Reserved           = 10;   // Animated frame parameters : LOWRD = FrameWidth, HIWRD = FrameCount

const int ZI_ZoomWindow         = 11;   // Version 1.41
const int ZI_ZoomFactor         = 12;   // Version 1.41
const int ZI_Orientation        = 13;   // Version 1.41

const int ZI_FlagByte           = 14;   // Version 2.00 4 bytes reserved for flag
const int    TOOL_CROP          = 1;    // Stored in the first byte
const int    TOOL_CUTTER        = 2;    // Stored in the first byte
const int    TOOL_PENCIL        = 4;    // Stored in the first byte
const int    TOOL_FLOOD         = 8;    // Stored in the first byte
const int    TOOL_AIRBRUSH      = 16;   // Stored in the first byte
const int    TOOL_PIPE          = 32;   // Stored in the first byte
const int    TOOL_MOUSE         = 64;   // Stored in the first byte
const int    TOOL_UNKNOWN       = 128;  // Stored in the first byte

const int Extend_cbWndExtra     = ZI_FlagByte;

const int ZI_GDIPLUSHANDLE      = 1;    // Load GDIPLUS Image handle

const int ZI_GLDC               = 8;    // OpenGL Device Context
const int ZI_GLRC               = 9;    // OpenGL Rendering Context

const int ZD_MAPCOLORFROM       = 0x807F80;   // Maping color for 32-bit alphablending
const int ZI_MAPCOLORFROM       = 0xFF807F80; // Maping color for 32-bit alphablending
const int ZI_MAPCOLORTO         = 0xFF808080; // Maping color for 32-bit alphablending
const int ZI_MAPCOLORNULL       = 0x00807F80; // Maping color for 32-bit alphablending
const int ZI_MAPTRANSCOLOR      = 0x807F80;   // Transparent maped color for 32-bit alphablending

extern "C" _declspec (dllexport) wchar_t* ZI_Version();
extern "C" _declspec (dllexport) long RegisterGLImageClass();
extern "C" _declspec (dllexport) HINSTANCE zInstance();
extern "C" _declspec (dllexport) void ZI_SetProperty (IN HWND hWnd, IN long nItem, IN long nValue);
extern "C" _declspec (dllexport) long ZI_GetProperty (IN HWND hWnd, IN long nItem);
extern "C" _declspec (dllexport) void ZI_GetBitmapSize (IN HANDLE hBmp, OUT long xWidth, OUT long yHeight);
extern "C" _declspec (dllexport) HANDLE ZI_GetBMP (IN HWND hWnd);
extern "C" _declspec (dllexport) void ZI_GetImageSizeFromControl (IN HWND hWnd, OUT long imgW, OUT long imgH);
extern "C" _declspec (dllexport) HBITMAP zCreateDIBSection (IN HDC hDC, IN long nWidth, IN long nHeight, IN long nBitCount);


And here is the begining of GDImage.cpp (work in progress)// GDImage.cpp : définit les fonctions exportées pour l'application DLL.
//
#include <windows.h>
#include <iostream>
#include <string.h>
#include <WinGDI.h>
#include <gl/GL.h>
#include <gl/GLU.h>

#include "stdafx.h"
#include "GDImage.h"

typedef struct {
    HWND    hWnd;
    LONG    anchor;
    RECT    rc;
    LONG    TiledBitmap;
    CHAR    order[METADATA_SIZE];
    LONG    ordersize;
    LONG    WMBit[25];
    DWORD   WMCodePtr[25 * 32];
    LONG    centerx;
    LONG    centery;
    LONG    Composited;
} ZIMAGEPROP;

typedef struct {
    HWND    hWnd;
    long    hTexture;
    BYTE    CharWidth[256];
    long    nFontSize;
    TCHAR   szFontName[64];
} CHARTFONT;

static wchar_t *Version = L"6.06";

// Global variables
CHARTFONT g_GLF[];

HBITMAP zCreateDIBSection (IN HDC hDC, IN long nWidth, IN long nHeight, IN long nBitCount) { // exportdll
    BITMAPINFO bi = { 0 };
    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bi.bmiHeader.biWidth = nWidth;
    bi.bmiHeader.biHeight = nHeight;
    bi.bmiHeader.biPlanes = 1;
    bi.bmiHeader.biBitCount = nBitCount;
    bi.bmiHeader.biCompression = BI_RGB;
    return CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, 0, 0, 0);
}

long SetupPixelFormat(IN HDC hDC, IN long FlagStyle) {
    PIXELFORMATDESCRIPTOR pfd;
    long pixelformat;
    long lRet;

    lRet = TRUE;

    pfd.nSize              = sizeof(pfd);
    pfd.nVersion           = 1;
    pfd.dwFlags            = FlagStyle;
    pfd.iPixelType         = 0;
    pfd.cColorBits         = 32;
    pfd.cRedBits           = 0;
    pfd.cRedShift          = 0;
    pfd.cGreenBits         = 0;
    pfd.cGreenShift        = 0;
    pfd.cBlueBits          = 0;
    pfd.cBlueShift         = 0;
    pfd.cAlphaBits         = 1;
    pfd.cAlphaShift        = 0;
    pfd.cAccumBits         = 0;
    pfd.cAccumRedBits      = 0;
    pfd.cAccumGreenBits    = 0;
    pfd.cAccumBlueBits     = 0;
    pfd.cAccumAlphaBits    = 0;
    pfd.cDepthBits         = 16;
    pfd.cStencilBits       = 0;
    pfd.cAuxBuffers        = 0;
    pfd.iLayerType         = 0;
    pfd.bReserved          = 0;
    pfd.dwLayerMask        = 0;
    pfd.dwVisibleMask      = 0;
    pfd.dwDamageMask       = 0;

    pixelformat = ChoosePixelFormat(hDC, &pfd);
    if (pixelformat) {
        if (SetPixelFormat(hDC, pixelformat, &pfd) == 0) { lRet = FALSE; } }
    else {
       lRet = FALSE;
    }

    return lRet;
}

long zSetupPixelFormat(IN HDC hDC) {
    return SetupPixelFormat(hDC, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SUPPORT_GDI);
}

wchar_t* ZI_Version () { // dllexport
    return Version; // Version number of the form "#.#"
}

HINSTANCE zInstance () { // dllexport
    return GetModuleHandle(NULL);
}

void ZI_GetBitmapSize (IN HANDLE hBmp, OUT long xWidth, OUT long yHeight) { // dllexport
    BITMAP bm;
    if (hBmp) {
       GetObject(hBmp, sizeof(bm), &bm);
       xWidth = bm.bmWidth;
       yHeight = bm.bmHeight;
    }
}

HANDLE ZI_GetBMP (IN HWND hWnd) { // dllexport
    return HANDLE(ZI_GetProperty(hWnd, ZI_Bitmap));
}

void ZI_GetImageSizeFromControl (IN HWND hWnd, OUT long imgW, OUT long imgH) { // dllexport
    ZI_GetBitmapSize(ZI_GetBMP(hWnd), imgW, imgH);
}

long ZI_GetProperty (IN HWND hWnd, IN long nItem) { // dllexport
    long nRet = 0;
    if (nItem > 0 && nItem < Extend_cbWndExtra + 1 && IsWindow(hWnd)) {
        nRet = GetWindowLong(hWnd, (nItem - 1) * 4);
    }
    return nRet;
}

void ZI_SetProperty (IN HWND hWnd, IN long nItem, IN long nValue) { // dllexport
    if (nItem > 0 && nItem < Extend_cbWndExtra + 1 && IsWindow(hWnd)) {
        SetWindowLong(hWnd, (nItem - 1) * 4, nValue);
    }
}

LRESULT CALLBACK zGLWindowProc(IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) {
    PAINTSTRUCT ps;
    HDC glDC;
    HGLRC glRC;

    switch (uMsg) {
    case WM_CREATE:
         glDC = GetDC(hWnd);

         if (zSetupPixelFormat(glDC) == 0) {
            return 1;
         }
         glRC = wglCreateContext(glDC);
         wglMakeCurrent(glDC, glRC);

         ZI_SetProperty(hWnd, ZI_GLDC, long(glDC));
         ZI_SetProperty(hWnd, ZI_GLRC, long(glRC));
         return 0;

    case WM_PAINT:
         BeginPaint(hWnd, &ps);
         EndPaint(hWnd, &ps);
         return 0;

    case WM_DESTROY:
         glDC = HDC(ZI_GetProperty(hWnd, ZI_GLDC));
         glRC = HGLRC(ZI_GetProperty(hWnd, ZI_GLRC));
         if (glRC) {
            wglMakeCurrent(glDC, 0);
            wglDeleteContext(glRC); glRC = 0;
         }
         if (glDC) { ReleaseDC(hWnd, glDC); glDC = 0; }
//         GL_DeleteTextureFont(hWnd);
//         if GL_ChartProc(0,0) { SetWindowLong(GL_ChartWnd(0,0), GWL_WNDPROC, GL_ChartProc(0,0)); }
         break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

long RegisterGLImageClass () { // dllexport
    WNDCLASSEX wcx;
    wcx.cbSize = sizeof(wcx);
    long IsInitialized = GetClassInfoEx(zInstance(), GLImageClassName, &wcx);
    if (IsInitialized) {
        wcx.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
        wcx.lpfnWndProc   = zGLWindowProc;
        wcx.cbClsExtra    = 0;
        wcx.cbWndExtra    = Extend_cbWndExtra * 4;
        wcx.hInstance     = zInstance();
        wcx.hIcon         = NULL;
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcx.hbrBackground = NULL; // Don't paint the class window background
        wcx.lpszMenuName  = NULL;
        wcx.lpszClassName = GLImageClassName;
        wcx.hIconSm       = NULL;
        if (RegisterClassEx(&wcx)) { IsInitialized = TRUE; }
    }
    return IsInitialized;
}

//BOOL WINAPI DllMain(IN DWORD hDllHandle, IN DWORD nReason, IN LPVOID Reserved) {
//  BOOLEAN bRet = TRUE;
//
//  //  Perform global initialization.
//  if (nReason == DLL_PROCESS_ATTACH) {
//      }
//  else if (nReason == DLL_PROCESS_DETACH) {
//  }
//
// }


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
Title: Translating PB to C (UBOUND, REDIM PRESERVE)
Post by: Patrice Terrier on January 16, 2013, 01:53:37 PM
Here is a typical PowerBASIC syntax, that is hard to translate into C.

Using UBOUND on an array that has not been DIMed yet, and REDIM PRESERVE to change array size.

TYPE CHARTFONT
    hWnd            AS LONG
    hTexture        AS LONG
    CharWidth(255)  AS BYTE
    nFontSize       AS LONG
    szFontName      AS ASCIIZ * 64
END TYPE
       
GLOBAL g_GLF() AS CHARTFONT

FUNCTION GL_GetNewFontItem() AS LONG
    LOCAL nItem AS LONG
    IF UBOUND(g_GLF) > 0 THEN
       ARRAY SCAN g_GLF(LBOUND(g_GLF)), FROM 1 TO 4, = MKL$(0), TO nItem
    END IF
    IF nItem = 0 THEN
       nItem = MAX&(UBOUND(g_GLF) + 1, 1)
       REDIM PRESERVE g_GLF(1 TO nItem) AS CHARTFONT
    END IF
    FUNCTION = nItem
END FUNCTION


Suggestion welcomed!
Title: Re: Get prepared to move on.
Post by: Stan Duraham on January 16, 2013, 03:12:59 PM
If you don't need to Insert or Delete items in the middle of the array, then it's easy to roll your own.

use: GlobalAlloc(ByVal %GPTR, ByVal Count) to allocate memory for an empty array.
use: GlobalReAlloc(ByVal h, ByVal Count, ByVal %GMEM_MOVEABLE Or %GMEM_ZEROINIT) to allocate a larger or smaller memory block.

Count = number of bytes

GlobalReAlloc(), with those flags, will preserve the data.
GlobalReAlloc() may return a different memory handle.
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 16, 2013, 04:13:49 PM
Stanley,

Your GMem solution is a good one, however it envolves a lot of changes to the original PB's syntax being used...
I mean using a global memory pointer, instead of a global array().

:-\

Stan's memory manager:
Function LibMemAlloc(ByVal Count As Long) As Long
    'allocate Count bytes of memory
    If Count Then
        Function = GlobalAlloc(ByVal %GPTR, ByVal Count)
    End If
End Function
Function LibMemFree(ByVal h As Long) As Long
    'free allocated memory - return null
    If h Then GlobalFree(ByVal h)
End Function
Function LibMemReAlloc(ByVal h As Long, ByVal Count As Long) As Long
    'change allocation block size
    'current contents saved
    'if Count > current allocation - additional memory will be null
    'USE: h = LibMemReAlloc(h, newSize)
    If Count = 0 Then
        If h Then GlobalFree(ByVal h)
    Else
        If h Then
            Function = GlobalReAlloc(ByVal h, ByVal Count, ByVal %GMEM_MOVEABLE Or %GMEM_ZEROINIT)
        Else
            Function = GlobalAlloc(ByVal %GPTR, ByVal Count)
        End If
    End If
End Function
Sub LibMemCopy(ByVal copyTo As Long, ByVal copyFrom As Long, ByVal Count As Long)
    'copy/move block of memory
    If Count Then MoveMemory(ByVal copyTo, ByVal copyFrom, ByVal Count)
End Sub
Title: Re: Get prepared to move on.
Post by: Stan Duraham on January 16, 2013, 04:15:59 PM
welcome to C
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 16, 2013, 04:23:11 PM
Stanley,

I am not moving to C on happy heart, but because i don't want to be an hostage anymore.

  :)
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 16, 2013, 04:34:10 PM
Stanley--

In the case of a DLL, don't you think that HeapCreate could be a better choice, than using GlobalAlloc ?

...

Title: Re: Get prepared to move on.
Post by: Stan Duraham on January 16, 2013, 05:30:06 PM
I don't know.
That's all I've tried because it works so well for arrays.
GlobalReAlloc, with those flags, is like REDIM PRESERVE with no extra work.
I had no problems with DLLs.
Title: Re: Get prepared to move on.
Post by: Charles Pegge on January 16, 2013, 07:18:41 PM
One of the biggest challenges is to make a good string engine with concatenator and garbage collection. You can still use OLEstrings like PB. They are also good for dynamic arrays up to 2 gig of data.

Having been through all the logistics of dynamic string management (using Assembler), I would be very happy to share ideas on how this might be achieved in C.

Charles



Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 16, 2013, 07:27:34 PM
I've always tended to use the GlobalAlloc() family of functions, rather than the HeapCreate()/HeapAlloc(), but its likely just inirtia with me. 

My question on C compilation as opposed to C++ compilation was simply based on the idea that C++ compilation, as you are apparently doing if you terminate your filenames with *.cpp instead of *.c, gives some ease of use type benifits that I believe are significant, without incurring any negatives.  To give just one example, in a lot of ways you can eliminate the typedef key word around structs if you do C++ compiulation.  The following will compile in C as Main.c ...


// C Way ...
#include <cstdio>

struct SomeStruct
{
int a;
int b;
};

int main(void)
{
struct SomeStruct ss;

ss.a=5, ss.b=6;
printf("ss.a = %d\n",ss.a);
printf("ss.b = %d\n",ss.b);
getchar();

return 0;
}



Note in main() I had to preface the SomeStruct declaration with the struct keyword.  However, one can get away from that to a more natural usage in straight C by using the typedef ...


#include <cstdio>

typedef struct
{
int a;
int b;
}SomeStruct;

int main(void)
{
SomeStruct ss;

ss.a=5, ss.b=6;
printf("ss.a = %d\n",ss.a);
printf("ss.b = %d\n",ss.b);
getchar();

return 0;
}


Note carefully the few changes above.  Using the typedef in the definition of SomeStruct, I was able to eliminate the use of the struct keyward before the declaration of the SomeStruct object in main().  So there you see where and why the typedef is on so many darned UDTs in the documentation;  its because folks want the stuff to compile with either a C or C++ compiler.   And that might be true in your case too.  But if you stick to straight C++ compilation, you can eliminate the dumb typedefs.  Here's same program using C++ compilation ...


//C++ way ...
#include <cstdio>

struct SomeStruct
{
int a;
int b;
};

int main(void)
{
SomeStruct ss;

ss.a=5, ss.b=6;
printf("ss.a = %d\n",ss.a);
printf("ss.b = %d\n",ss.b);
getchar();

return 0;
}


Of course, there are other benifits too, such as Byref parameter passing (like PowerBASIC), so that is the only point I was trying to make.

Since I work back and forth so frequently between C/C++ and PowerBASIC, I've always tended to use only that subset of PowerBASIC that has ready analogues in C.  For example, your use of Array Sort above pretty much 'threw me', as I tend not to use such constructs.  I tend to write pretty low level in both language families.  So I can see where it will be difficult translating your code Patrice.

I will say it is time consumming doing line by line translating between C and PB.  CreateWindowEx() calls are a real bear.  I mean, they look so similiar, but everyone takes like a whole minute to do.  One must ...

1) insert semicolon;
2) replace 'Or' with '|';
3) stick Byval 0 for lpCreateParams;
4) remove '%';
5) deal with wide character issue using TCHARs or whatever you do

etc.  In my example programs I've posted here where I'll provide C++ and exact PowerBASIC versions of the same program, it can easy take an hour or two to convert only a simple 200 line example program.     
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 16, 2013, 07:35:36 PM
Quote
One of the biggest challenges is to make a good string engine with concatenator and garbage collection. You can still use OLEstrings like PB. They are also good for dynamic arrays up to 2 gig of data.

How right you are Charles!  That, in my mind, is where the fatal flaw in C++ lies.  The language has no built in 'String' type.  Its rather part of the C++ Standard Library.  In my opinion, even though the String Class in the C++ Standard Library is extremely good, its usage for the coder doesn't match what is available in various good versions of BaSIC, such as PowerBASIC.  What Bob Zale must have know about writting String code!!!!!
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 16, 2013, 07:43:45 PM
Quote
Having been through all the logistics of dynamic string management (using Assembler), I would be very happy to share ideas on how this might be achieved in C.

For the next little while I'll be busy on some things at work that I have to get done, but at some point in the future I'd love to work on that Charles.  As you know, I made my own String class I use in my C++ coding.  However, its only based on null terminated string buffers, i.e., allocate buffer, terminate with NULL - you know the drill.  I'd like to try to make another based on OLE String Engine as you mentioned.
Title: Re: Get prepared to move on.
Post by: Charles Pegge on January 16, 2013, 09:12:56 PM

The genius of the OLEstring is that is has both a null terminator and has a hidden length field (offset-4), so in many situations it can be used precisely as a null-terminated string - passing string data to the API, for instance.

Only two calls are essential:
SysAllocStringByteLen
SysFreeString
Title: Re: Get prepared to move on.
Post by: James Klutho on January 16, 2013, 09:33:40 PM
C's weakness in strings is the main reason I switched from C to Powerbasic around the year 2001.  I love dynamic strings and Powerbasic's trunk full of operations on them.  If C had better string handling I would probably still be there.
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 16, 2013, 09:36:33 PM
Quote
The genius of the OLEstring is that ...

And of course, the bad news is that, even so,  its still not very smart.  You can't concatenate them, call Parse() or InStr() on them, or do anything whatsoever in C or C++ like we do with PowerBASIC dynamic strings (whose underlying type is the OLEString). 

I know there has been a massive effort on this by C++ coders everywhere, so it would likely be a worthwhile goal to investigate some of that work out there.  On the other hand, I already have a decent string class of my own that I might be able to modify so as to incorporate BSTRs instead of my new[] allocated buffers.     
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 16, 2013, 10:31:03 PM
Discussion of this (my favorite topic, other than COM - Strings!) caused me to lookup a fun old program of mine.  Its a little GUI program that exercises my C++ string class using many of the customary PowerBASIC coding calls we so love such as InStr(), Left(), Right(), Mid(), ParseCount(), Parse, concatenation, etc.  Of course, its in C++.  The header for the string class looks like this ...


//Strings.h
#if !defined(STRINGS_H)
#define STRINGS_H
#define EXPANSION_FACTOR      2
#define MINIMUM_ALLOCATION   16

class String
{
public:
friend String operator+(TCHAR*, String&);
String();                                    //Uninitialized Constructor
String(const TCHAR);                         //Constructor Initializes With A TCHAR.
String(const TCHAR*);                        //Constructor Initializes String With TCHAR*
String(const String&);                       //Constructor Initializes String With Another String (Copy Constructor)
String(const int, bool);                     //Constructor Creates String With User Specified Capacity and optionally nulls out
String(const int, const TCHAR);              //Constructor initializes String with int # of TCHARs
String(int);                                 //Constructor initializes String with int converted to String
String(unsigned int);                        //Constructor initializes String with unsigned int converted to String
String(double);                              //Constructor initializes String with double converted to String
String& operator=(const TCHAR);              //Assign A TCHAR To A String
String& operator=(const TCHAR*);             //Assign A Null Terminated TCHARacter Array To A String
String& operator=(const String&);            //Assigns Another String To this One
String& operator=(int iNum);                 //Assigns an unsigned int to a String
String& operator=(unsigned int iNum);        //Assigns an unsigned int to a String
String& operator=(double dblNum);            //Assign a double to a String
String operator+(const TCHAR);               //For adding TCHAR to String
String operator+(const TCHAR*);              //Adds a TCHAR* to this
String operator+(String&);                   //Adds another String to this
String& operator+=(const TCHAR ch);          //Add TCHAR to this
String& operator+=(const String&);           //Adds a String to this and assigns it to left of equal sign
String& operator+=(const TCHAR*);            //Adds a TCHAR*to this and assigns it to left of equal sign
bool operator==(String&);                    //Compares Strings For Case Sensitive Equality
bool operator==(const TCHAR*);               //Compares String Against TCHAR* For Case Sensitive Equality
String& Make(const TCHAR ch, int iCount);    //Returns reference to this with iCount ch TCHARs in it
String Left(int);                            //Returns String of iNum Left Most TTCHARs of this
String Right(int);                           //Returns String of iNum Right Most TTCHARs of this
String Mid(int, int);                        //Returns String consisting of number of TTCHARs from some offset
String Replace(TCHAR*, TCHAR*);              //Returns String with 1st TCHAR* parameter replaced with 2nd TCHAR* parameter
String Remove(TCHAR*);                       //Returns A String With All The TCHARs In A TCHAR* Removed (Individual TCHAR removal)
String Remove(const TCHAR*, bool);           //Returns a String with 1st parameter removed.  2nd is bool for case sensitivity.
int InStr(const TCHAR*, bool);               //Returns one based offset of a particular TTCHAR pStr in a String
int InStr(const String&, bool);              //Returns one based offset of where a particular String is in another String
int ParseCount(const TCHAR);                 //Returns count of Strings delimited by a TTCHAR passed as a parameter
void Parse(String*, TCHAR);                  //Returns array of Strings in first parameter as delimited by 2nd TTCHAR delimiter
void SetTCHAR(int, TCHAR);                   //Sets TCHAR at zero based offset in this
void LTrim();                                //Returns String with leading spaces/tabs removed
void RTrim();                                //Returns String with spaces/tabs removed from end
void Trim();                                 //Returns String with both leading and trailing whitespace removed
int iVal();                                  //Returns integral value of String
int Len();                                   //Returns Length Of String Controlled By this
int Capacity();                              //Returns Maximum Permissable TCHARacter Count (One Less Than Allocation).
TCHAR* lpStr();                              //Returns TCHAR* To String
void Print(bool);                            //Outputs String To Console With Or Without CrLf.
~String();                                   //String Destructor

private:
TCHAR* lpBuffer;
int   iLen;
int   iCapacity;
};

String operator+(TCHAR* lhs, String& rhs);
#endif  //#if !defined(STRINGS_H)


From the 'private' data members of the class, you can see I catch the pointer to the underlying string buffer (this->lpBuffer), the length of the string presently in it (this->iLen), and the present capacity of the allocated buffer (this->iCapacity).  This is pretty much standard practice.  Its also designed to have a MINIMUM_ALLOCATION and an EXPANSION_FACTOR.  These come into play to facilitate rapid string concatenations.  It works with the TCHAR macros, so can run either ansi or wide character.

For anyone wishing to test this demo, the String.cpp file is here on Jose's site in Post #42 here ...

http://www.jose.it-berater.org/smfforum/index.php?topic=4176.30

Its the 3rd file in my Post #42.

Here is a fun little program exercising the string class ...


//Main.cpp
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "StrDemo.h"
#include "frmOutput.h"
#include "Strings.h"


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
TCHAR szClassName[]=_T("frmOutput");
WNDCLASSEX wc;
HWND hCtrl;

Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
wc.lpszClassName=szClassName;                          wc.lpfnWndProc=frmOutput;
wc.cbSize=sizeof (WNDCLASSEX);                         wc.style=CS_DBLCLKS;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);               wc.hInstance=Wea->hIns;
wc.hIconSm=NULL;                                       wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);  wc.cbWndExtra=0;
wc.lpszMenuName=NULL;                                  wc.cbClsExtra=0;
RegisterClassEx(&wc);
hCtrl=CreateWindow(_T("button"),_T("String Concatenation"),WS_CHILD|WS_VISIBLE,45,20,250,25,Wea->hWnd,(HMENU)IDC_CONCATENATION,Wea->hIns,0);
hCtrl=CreateWindow(_T("button"),_T("String Parsing And Trimming"),WS_CHILD|WS_VISIBLE,45,55,250,25,Wea->hWnd,(HMENU)IDC_PARSE,Wea->hIns,0);
hCtrl=CreateWindow(_T("button"),_T("Good Old Left, Right, And Mid!"),WS_CHILD|WS_VISIBLE,45,90,250,25,Wea->hWnd,(HMENU)IDC_LEFT_RIGHT_MID,Wea->hIns,0);
hCtrl=CreateWindow(_T("button"),_T("But Led's Not Forget InStr( )!"),WS_CHILD|WS_VISIBLE,45,125,250,25,Wea->hWnd,(HMENU)IDC_INSTR,Wea->hIns,0);

return 0;
}


void btnConcatenation_OnClick(void)
{
HWND hOutput;
String s;
int iY=0;
HDC hDC;

hOutput=CreateWindow(_T("frmOutput"),_T("String Class Minipulations In C++"),WS_OVERLAPPEDWINDOW,450,20,305,480,0,0,GetModuleHandle(0),0);
ShowWindow(hOutput,SW_SHOWNORMAL);
hDC=GetDC(hOutput);
for(unsigned int i=65; i<91; i++)
{
     s=s+i;                                   //65 Is Capital 'A'
     TextOut(hDC,0,iY,s.lpStr(),s.Len());     //TextOut() is the Windows Version Of Basic's 'Print'
     iY=iY+16;                                //A Spacing Of 16 Pixels Works Good For Most Normal Sized Fonts
}
ReleaseDC(hOutput,hDC);
}


void btnParse_OnClick(void)
{
String* ptrStrings;
unsigned int iCt;
HWND hOutput;
String s;
int iY=0;
HDC hDC;

hOutput=CreateWindow(_T("frmOutput"),_T("String Class Minipulations In C++"),WS_OVERLAPPEDWINDOW,50,400,310,180,0,0,GetModuleHandle(0),0);
ShowWindow(hOutput,SW_SHOWNORMAL);
hDC=GetDC(hOutput);
s=_T("Frederick,  Mary,  James,  Samuel,  Edward,  Richard,  Michael,  Joseph");  //Create comma delimited text string
iCt=s.ParseCount(_T(','));                                                        //Count delimited substrings
ptrStrings = new String[iCt];                                                     //Create array of String Pointers
s.Parse(ptrStrings,_T(','));                                                      //Parse 's' based on comma delimiter
for(unsigned int i=0; i<iCt; i++)
{
     ptrStrings[i].LTrim();  //Comment This Out To See Effect.                     //There are some spaces in delimited strings so remove them
     TextOut(hDC,0,iY,ptrStrings[i].lpStr(),ptrStrings[i].Len());                  //Output/Print array of strings one at a time
     iY=iY+16;
}
delete [] ptrStrings;
ReleaseDC(hOutput,hDC);
}


void btnLeftRightMid_OnClick(void)
{
HWND hOutput;
String s1,s2;
HDC hDC;

hOutput=CreateWindow(_T("frmOutput"),_T("String Class Minipulations In C++"),WS_OVERLAPPEDWINDOW,800,100,325,250,0,0,GetModuleHandle(0),0);
ShowWindow(hOutput,SW_SHOWNORMAL);
hDC=GetDC(hOutput);
s1=_T("George Washington Carver");
s2=s1.Left(6);
TextOut(hDC,20,20,s1.lpStr(),s1.Len());
TextOut(hDC,20,40,s2.lpStr(),s2.Len());
s2=s1.Mid(8,10);
TextOut(hDC,20,60,s2.lpStr(),s2.Len());
s2=s1.Right(6);
TextOut(hDC,20,80,s2.lpStr(),s2.Len());
ReleaseDC(hOutput,hDC);
}


void btnInStr_OnClick(void)
{
String s1,s3;
double dblPi;
HWND hOutput;
HDC hDC;

hOutput=CreateWindow(_T("frmOutput"),_T("String Class Minipulations In C++"),WS_OVERLAPPEDWINDOW,550,575,525,200,0,0,GetModuleHandle(0),0);
ShowWindow(hOutput,SW_SHOWNORMAL);
hDC=GetDC(hOutput);
s1=_T("InStr('Some Text') Locates The One Based Offset Of Where Something Is At.");
TextOut(hDC,0,0,s1.lpStr(),s1.Len());
s1=_T("C++ Can Be A Real Pain In The Butt To Learn!");
TextOut(hDC,0,16,s1.lpStr(),s1.Len());
String s2(s1.InStr(_T("real"),false));
s3 =_T("The Offset Of 'real' In The Above String Is ");
s3 = s3 + s2 + _T('.');
TextOut(hDC,0,32,s3.lpStr(),s3.Len());
s1=_T("Note In The Above Code We Used The Case Insensitive Version Of InStr().");
TextOut(hDC,0,48,s1.lpStr(),s1.Len());
s1=_T("Let's See If We Can Remove() 'Real' From Our 1st String!");
TextOut(hDC,0,64,s1.lpStr(),s1.Len());
s1=_T("C++ Can Be A Real Pain In The Butt To Learn!");
TextOut(hDC,0,80,s1.lpStr(),s1.Len());
s2=s1.Remove(_T("Real"),true);
TextOut(hDC,0,96,s2.lpStr(),s2.Len());
s1=_T("Dieses Program funktioniert aber sehr gut, nicht wahr?");
TextOut(hDC,0,112,s1.lpStr(),s1.Len());
dblPi=3.14159;
s1=_T("dblPi = ");
s2=dblPi;
s1=s1+s2;
TextOut(hDC,0,128,s1.lpStr(),s1.Len());
ReleaseDC(hOutput,hDC);
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
switch(LOWORD(Wea->wParam))
{
  case IDC_CONCATENATION:
    btnConcatenation_OnClick();
    break;
  case IDC_PARSE:
    btnParse_OnClick();
    break;
  case IDC_LEFT_RIGHT_MID:
    btnLeftRightMid_OnClick();
    break;
  case IDC_INSTR:
    btnInStr_OnClick();
    break;
}

return 0;
}


long fnWndProc_OnDestroy(lpWndEventArgs Wea)
{
PostQuitMessage(0);
return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
WindowsEventArguments Wea;

for(unsigned int i=0; i<dim(EventHandler); i++)
{
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
}

return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
TCHAR szClassName[]=_T("StrDemo");
WNDCLASSEX wc;
MSG messages;
HWND hWnd;

wc.lpszClassName=szClassName;                wc.lpfnWndProc=fnWndProc;
wc.cbSize=sizeof (WNDCLASSEX);               wc.style=0;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);     wc.hInstance=hIns;
wc.hIconSm=0,                                wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;    wc.cbWndExtra=0;
wc.lpszMenuName=NULL;                        wc.cbClsExtra=0;
RegisterClassEx(&wc);
hWnd=CreateWindow(szClassName,_T("StrDemo"),WS_OVERLAPPEDWINDOW,20,20,350,210,HWND_DESKTOP,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
    TranslateMessage(&messages);
    DispatchMessage(&messages);
}

return messages.wParam;
}



//frmOutput.cpp  All this file consists of is the Window Procedure for the frmOutput
//Window Class.  A window of class frmOutput is created whose sole purpose is to be
//printed to with TextOut().  All default window procedure processing is ok so the
//window procedure frmOutput doesn't have to do anything on its own other than exist
//and pass all messages received onto DefWindowProc().  It has to exist because its
//referenced in the Class Registration code in fnWndProc_OnCreate() where the frmOutput
//class is registered. 
#include <windows.h>
#include "frmOutput.h"

long __stdcall frmOutput(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
return (DefWindowProc(hwnd, msg, wParam, lParam));
}




//StrDemo.h
#ifndef StrDemo_h
#define StrDemo_h

#define IDC_CONCATENATION       1500
#define IDC_PARSE               1505
#define IDC_LEFT_RIGHT_MID      1510
#define IDC_INSTR               1515

#define dim(x) (sizeof(x) / sizeof(x[0]))

struct                          WindowsEventArguments
{
HWND                           hWnd;
WPARAM                         wParam;
LPARAM                         lParam;
HINSTANCE                      hIns;
};

typedef WindowsEventArguments*  lpWndEventArgs;

long fnWndProc_OnCreate         (lpWndEventArgs Wea);
long fnWndProc_OnCommand        (lpWndEventArgs Wea);
long fnWndProc_OnDestroy        (lpWndEventArgs Wea);

void btnConcatenation_OnClick   (void);
void btnParse_OnClick           (void);
void btnLeftRightMid_OnClick    (void);
void btnInStr_OnClick           (void);

struct EVENTHANDLER
{
unsigned int                   iMsg;
long                           (*fnPtr)(lpWndEventArgs);
};

const EVENTHANDLER EventHandler[]=
{
{WM_CREATE,                    fnWndProc_OnCreate},
{WM_COMMAND,                   fnWndProc_OnCommand},
{WM_DESTROY,                   fnWndProc_OnDestroy}
};

#endif



//frmOutput.h
long __stdcall frmOutput(HWND, unsigned int, WPARAM, LPARAM);


What the program does is create a little window with I believe five buttons on it.  Each button says what string functions its going to exercise.  When you click a button it outputs to another window various strings it minipulated in some way.  Just tested it with Code::Blocks and MinGW.  Should work OK.
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 17, 2013, 09:31:23 AM
Jim--

QuotePatrice, do you think you'll end up with a "PowerBASIC to C" translator after all your work???
Or are you just doing it by hand?

I thought about writing my own translator, but for now i am doing everything by hand, because i am still learning most of the C syntax, thus i have to do much try before i could get the good syntax, and many of the PowerBASIC keywords need to be rewriten/translated from ground zero.

The nastiest thing i am faced with, is the strong typing of C, making hard to use "long" or "dword" like in PB.
For example: HANDLE, HDC, HBITMAP, HWND, etc. are all "long/dword" but they could not be intermixed together, because of the way they are declared in the SDK headers.

???
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 17, 2013, 11:13:39 AM
Fred,
  What is your main problem with c++ STL strings?
I wrote wrapper functions for a number  of the "BASIC "functions  (mid,left,right,trim....) for one of my first forks of BCX.

James
Title: Re: Get prepared to move on.
Post by: Theo Gottwald on January 17, 2013, 12:06:48 PM
Charles, I'd prefer to have a PB compatible Compiler that can generate x64.
How long do you think would it take if you'd make one?  ;D
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 17, 2013, 12:17:06 PM
Theo--

Translating 32-bit to 64-bit envolved much changes, especially when you have to deal with memory offset.

And some constants are not valid anymore, for example GWL_WNDPROC becomes GWLP_WNDPROC, much headache in perspective before you could get a 64-bit code to work (even if it compiles).

Rules for Using Pointers (http://msdn.microsoft.com/en-us/library/windows/desktop/aa384242(v=vs.85).aspx).

...
Title: Re: Get prepared to move on.
Post by: Theo Gottwald on January 17, 2013, 01:45:37 PM
I trust in Charles. He knows that already.

If you want, test his 64 bit compiler.

He must just change the syntax to be PB compatible, then a LOT may already compile.
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 17, 2013, 03:46:15 PM
That PureBasic compiler sure looks like a good fit to me.  I'm staying with PowerBASIC myself, as I don't have any need for 64 bit yet, but different times I've thought of buying it just to play with like Theo did.  From what Patrice said, its developed by a team of programmers instead of just one, which is an advantage, and it does do 64 bit apparently. 

I guess my main gripes about STL James are the bloated executables.  And that's just me.  I know in the grand scheme of things it isn't important to anybody but me.  I suppose I measure everything against the small size, power, and performance of C or PowerBASIC code.   

 
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 17, 2013, 04:15:01 PM
QuotePatrice said, its developed by a team of programmers instead of just one

No, Patrice didn't said that, i said you will swap Bob Zale with Frédéric Laboureur (main programmer), meaning this could lead to the same issue sooner or later.

And about Charles, with all my respect, that would be probably the same issue.

On the other hand, i couldn't see how C/c++ would disapeared.

Also, speaking for myself, there is no comparison between the C/C++ addon market, and the small PB's one, i can make already the comparison with PB and WinDev, doing 90% of my business with PC-Soft.


...
Title: Re: Get prepared to move on.
Post by: Frederick J. Harris on January 17, 2013, 11:23:51 PM
I see what you mean Patrice.  Today I actually spent a little time examining the situation with PureBasic, and I reread Theo's detailed writeup once again, which I read when he first posted it, but I  had forgotten the details.  I'd be really 'put off' by the fact that the language doesn't require code to be within a procedure (like PB DOS, and all older versions of BASIC).  In fact, I'd reject it out of hand for that reason alone.  That may be unfair, I admit, but its just me.  I realize if one would spend a lot of time writting assembler one might come to an acceptance of that as not anything significant, a matter of form over substance, so to speask, but I've been with more modern highly structured languages long enough that I wouldn't be able to get past that one.

I recall a discussion Charles and I had a long time ago about FreeBasic.  I learned from him that was the situation there too.  That's why I didn't persue any further investigation of FreeBasic.  I'm beginning to wonder if PowerBASIC is the only version of Basic that follows the more modern convention of requiring all code to be within function blocks?  I believe your Bcx doesn't allow code lines scattered about does it James?
Title: Re: Get prepared to move on.
Post by: James C. Fuller on January 18, 2013, 12:16:47 AM
Quote from: Frederick J. Harris on January 17, 2013, 11:23:51 PM
I believe your Bcx doesn't allow code lines scattered about does it James?

As a matter of fact it does but it's not just hanging out there!
Any code not in a function is stuffed into main or WinMain.

James
Title: Re: Get prepared to move on.
Post by: Charles Pegge on January 18, 2013, 05:42:22 AM

It is quite feasible to create a PowerBasic emulation/front-end with Oxygen, since unlike C, it has the essential core constructs, including dynamic string expressions, and COM object support.

I provide all the source code for Oxygen without licensing restrictions, and most of it is written in Basic. I trust this substantially addresses the problem of vendor lock-in :)

However, PowerBasic has a much much larger set  of commands and functions. To build these would be a major undertaking requiring some fairly intensive team work. It is not an quick fix.

The full PB emulatior option would be worth considering if PB were to become moribund, without prospect of further progress. But I hope the PowerBasic developers will be able to build upon Bob's work and take PB forward in a timely manner. This is how it should be.
Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 18, 2013, 02:17:12 PM
Charles,

QuoteTo build these would be a major undertaking requiring some fairly intensive team work. It is not an quick fix.

In the long run, i have never seen an intensive team work, going to full completion without some kind of financial support.

But of course dreaming, doesn't cost anything  :)

Title: Re: Get prepared to move on.
Post by: Charles Pegge on January 18, 2013, 07:02:00 PM

Motivation has to be there certainly even it is only self-interest, but it does not have to be financial. I think José would agree.

Title: Re: Get prepared to move on.
Post by: Patrice Terrier on January 18, 2013, 07:26:18 PM
Charles,

My point is not about motivation.

But programming being very time consumming, it is very hard for people to work for free, for a long period of time, except if they don't need to earn their living anymore (retired or sponsored), and if they have a limited social life (ask your wife).

;D
Title: Re: Get prepared to move on.
Post by: Charles Pegge on January 18, 2013, 08:57:32 PM

My virtual wife agrees that programming is very time consuming, but so much better than watching TV.  ;D