<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[PowerBASIC Users Meeting Point - Portal]]></title>
		<link>http://pump.richheimer.de/</link>
		<description><![CDATA[PowerBASIC Users Meeting Point - http://pump.richheimer.de]]></description>
		<pubDate>Wed, 29 Apr 2026 05:35:35 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Enter PIN popup dialog in DLL.]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=128</link>
			<pubDate>Thu, 23 Apr 2026 14:54:46 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=23">Dale Yarker</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=128</guid>
			<description><![CDATA[A popup for user to enter a PIN for return to your app. The number of digits is specified in the call, and checked by the function in the DLL.<br />
<br />
Longer description<br />
at <a href="https://www.yarker-dsyc.info/Programs/Misc/PIN/Enter_PIN_DLL.html" target="_blank" rel="noopener" class="mycode_url">https://www.yarker-dsyc.info/Programs/Mi...N_DLL.html</a><br />
<br />
Source, compiled, icons and Help file in ZIP<br />
at <a href="https://www.yarker-dsyc.info/Programs/Misc/PIN/Enter_PIN.zip" target="_blank" rel="noopener" class="mycode_url">https://www.yarker-dsyc.info/Programs/Mi...er_PIN.zip</a><br />
<br />
DLL source: <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#compile dll<br />
#dim all<br />
'================================================================<br />
enum PIN_IDs singular<br />
  '%en_update group<br />
  ID_PINA1Txtbx = &amp;h3000&amp;<br />
  ID_PINA2Txtbx<br />
  ID_PINA3Txtbx<br />
  ID_PINA4Txtbx<br />
  ID_PINA5Txtbx<br />
  ID_PINA6Txtbx<br />
  ID_PINA7Txtbx<br />
  ID_PINA8Txtbx<br />
  ID_PINA9Txtbx<br />
  ID_PINB1Txtbx = &amp;h3010<br />
  ID_PINB2Txtbx<br />
  ID_PINB3Txtbx<br />
  ID_PINB4Txtbx<br />
  ID_PINB5Txtbx<br />
  ID_PINB6Txtbx<br />
  ID_PINB7Txtbx<br />
  ID_PINB8Txtbx<br />
  ID_PINB9Txtbx<br />
  '%bn_clicked group<br />
  ID_PINAExposeBtn<br />
  ID_PINBExposeBtn<br />
  ID_PINSubmitSnglBtn<br />
  ID_PINSubmitDuplBtn<br />
  ID_PINHelp<br />
  ID_PINCanx<br />
  'not selected in callback<br />
  ID_PINInstruLbl<br />
  ID_PINALbl<br />
  ID_PINBLbl                                    'type rect '<br />
end enum 'number up to &amp;h3FF reserved<br />
'<br />
%EM_SETPASSWORDCHAR = &amp;h00CC<br />
%wm_syscommand = &amp;h0112 '(not built into PBWin)<br />
%DT_CalcRect = &amp;h00000400<br />
#resource icon, PIN16, ".&#92;PIN16.ico"<br />
#resource icon, ShowPWon24, ".&#92;ShowPWon24.ico"<br />
#resource icon, ShowPWoff24, ".&#92;ShowPWoff24.ico"<br />
#resource icon, PINSubmit, ".&#92;PINSubmit48.ico"<br />
#resource icon, PINHelp, ".&#92;HelpQuesBtn48.ico"<br />
#resource icon, PINCanx, ".&#92;CancelPIN32.ico"<br />
global gIsVariableDigits, gNumOfDigits as long '(is in PIN_Enter and callback)<br />
global gEntryErrTitle as wstring<br />
declare function ShellExecute lib "Shell32.dll" alias "ShellExecuteW" ( _<br />
    byval hwnd as dword, lpOperation as wstringz, lpFile as wstringz, _<br />
    lpParameters as wstringz, lpDirectory as wstringz, byval nShowCmd as long) _<br />
    as dword<br />
<br />
'############################################################# the function ####<br />
function PIN_Enter alias "PIN_Enter" (byval hParent as dword, _<br />
                                      byval DualPIN as long, _<br />
                                      byval NumOfDigits as long) export as dword<br />
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<br />
  static Not1stCall, nFontMono14B as long<br />
  static gEntryErrTitle as wstring<br />
  static RatioX, RatioY as single<br />
  local hPIN_Dlg, PIN as dword<br />
  local TBY, TBX, ID_Dig, PosX as long<br />
  local InstruStr, DigCnt as wstring<br />
  '========================================================= initialization ====<br />
  '····························································· persistent ····<br />
  if Not1stCall = 0 then 'so it is first call<br />
    Not1stCall = -1<br />
    font new "Lucida Console", 14, 1, 1, 0, 0 to nFontMono14B<br />
    dialog default font "Segoe UI", 12, 0, 1<br />
    gEntryErrTitle = "PIN Entry Error"&#36;&#36;<br />
  end if<br />
  '······························································ each call ····<br />
  if (NumOfDigits &lt; 0) or (NumOfDigits &gt; 9) then 'check range<br />
    msgbox "The number of PIN digits can only be optionally"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"not used, or 0 to 9 digits long."&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"Not used or 0 is for a variable length PIN of"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"1 to 9 digigits. Otherwise the number of digits is"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"fixed by the using program."&#36;&#36;, _<br />
         &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
    exit function<br />
  end if<br />
  if NumOfDigits = 0 then 'variable number<br />
    gIsVariableDigits = -1<br />
    gNumOfDigits = 9<br />
  else<br />
    gNumOfDigits = NumOfDigits<br />
  end if<br />
  '================================================================= dialog ====<br />
  dialog new hParent, "Enter PIN."&#36;&#36;, _<br />
      0, 10, 200, 120, _<br />
   &nbsp;&nbsp;%ds_3dlook or %ds_modalframe or %ds_nofailcreate or %ds_setfont or _<br />
   &nbsp;&nbsp;%ws_caption or %ws_clipsiblings or %ws_dlgframe or %ws_popup or _<br />
   &nbsp;&nbsp;%ws_sysmenu, %ws_ex_left or %ws_ex_ltrreading to hPIN_Dlg<br />
  dialog set icon hPIN_Dlg, "PIN16"<br />
  '------------------------------------------------------- unit/pixel ratio ----<br />
  #if %pb_revision = &amp;h1004<br />
    dialog units hPIN_Dlg, 1000, 1000 to pixels TBY, TBX 'precycle longs<br />
  #else<br />
    dialog units hPIN_Dlg, 1000, 1000 to pixels TBX, TBY<br />
  #endif<br />
  RatioX = 1000 /TBX : RatioY =  1000 / TBY 'mult img px for button units<br />
  '------------------------------------------------------------- PIN instru ----<br />
  if DualPIN then<br />
    InstruStr = "The application requires dual entry for the requested "&#36;&#36; + _<br />
                "task. "&#36;&#36;<br />
  end if<br />
  if NumOfDigits then<br />
    InstruStr +="Enter the "&#36;&#36; + dec&#36;(gNumOfDigits) + " digit PIN. "&#36;&#36;<br />
  else<br />
    InstruStr += "The number of digits is not fixed. The PIN may be 4 "&#36;&#36; + _<br />
               &nbsp;&nbsp;"to 9 digits. Leave unused digits at right empty. "&#36;&#36;<br />
  end if<br />
  InstruStr += "The only characters allowed are ""0"" to ""9""."&#36;&#36;<br />
  control add label, hPIN_Dlg, %ID_PINInstruLbl, InstruStr,  _<br />
   &nbsp;&nbsp;5, 4, 185, 34, %ss_left, %ws_ex_left<br />
  control set color hPIN_Dlg, %ID_PINInstruLbl, -1, &amp;hFAFAFA<br />
  '---------------------------------------------------- "A" digit textboxes ----<br />
  control add label, hPIN_Dlg, %ID_PINALbl, "Enter PIN:"&#36;&#36;, _<br />
   &nbsp;&nbsp;4, 45, 42, 10, %ss_right, %ws_ex_left &nbsp;&nbsp;''55<br />
  '<br />
  PosX = 49<br />
  for ID_Dig = %ID_PINA1Txtbx to %ID_PINA1Txtbx + gNumOfDigits - 1<br />
    control add textbox, hPIN_Dlg, ID_Dig, ""&#36;&#36;, _<br />
     &nbsp;&nbsp;PosX, 44, 12, 10, %es_center or %es_number or %ws_border or _<br />
     &nbsp;&nbsp;%ws_tabstop or %es_password, %ws_ex_clientedge or %ws_ex_left<br />
    control set font hPIN_Dlg, ID_Dig, nFontMono14B<br />
    PosX += 15<br />
  next<br />
  '<br />
  control add imgbutton, hPIN_Dlg, %ID_PINAExposeBtn, "ShowPWon24", _<br />
   &nbsp;&nbsp;181, 43, 28 * RatioX, 28 * RatioY<br />
  if DualPIN = 0 then<br />
    control add imgbutton, hPIN_Dlg, %ID_PINSubmitSnglBtn, "PINSubmit", _<br />
     &nbsp;&nbsp;49 - (52 * RatioX), 59, 52 * RatioX, 52 * RatioY<br />
 &nbsp;&nbsp;' dialog set size hPIN_Dlg, 200, 75 + (52 * RatioY)<br />
  else<br />
  '---------------------------------------------------- "B" digit textboxes ----<br />
    PosX = 49<br />
    control add label, hPIN_Dlg, %ID_PINBLbl, "Reenter PIN:"&#36;&#36;, _<br />
     &nbsp;&nbsp;4, 60, 42, 10, %ss_right, %ws_ex_left &nbsp;&nbsp;''55<br />
    for ID_Dig = %ID_PINB1Txtbx to %ID_PINB1Txtbx + gNumOfDigits - 1<br />
      control add textbox, hPIN_Dlg, ID_Dig, ""&#36;&#36;, _<br />
       &nbsp;&nbsp;PosX, 60, 12, 10, %es_center or %es_number or %ws_border or _<br />
       &nbsp;&nbsp;%ws_tabstop or %es_password, %ws_ex_clientedge or %ws_ex_left<br />
      control set font hPIN_Dlg, ID_Dig, nFontMono14B<br />
      PosX += 15<br />
    next<br />
  '<br />
    control add imgbutton, hPIN_Dlg, %ID_PINBExposeBtn, "ShowPWon24", _<br />
     &nbsp;&nbsp;181, 59, 28 * RatioX, 28 * RatioY<br />
    control add imgbutton, hPIN_Dlg, %ID_PINSubmitDuplBtn, "PINSubmit", _<br />
     &nbsp;&nbsp;49 - (52 * RatioX), 75, 52 * RatioX, 52 * RatioY<br />
  end if<br />
  '----------------------------------------------------- "A" and "B" common ----<br />
  if DualPIN = 0 then<br />
    control add imgbutton, hPIN_Dlg, %ID_PINHelp, "PINHelp", _<br />
     &nbsp;&nbsp;191 - (99 * RatioX), 59, 52 * RatioX, 52 * RatioY<br />
    control add imgbutton, hPIN_Dlg, %ID_PINCanx, "PINCanx", _<br />
     &nbsp;&nbsp;191 - (36 * RatioX), 59 + (16 * RatioY), (36 * RatioX), (36 * RatioY)<br />
    dialog set size hPIN_Dlg, 200, 76 + (52 * RatioY)<br />
  else<br />
    control add imgbutton, hPIN_Dlg, %ID_PINHelp, "PINHelp", _<br />
     &nbsp;&nbsp;191 - (99 * RatioX), 75, 52 * RatioX, 52 * RatioY<br />
<br />
    dialog set size hPIN_Dlg, 200, 92 + (52 * RatioY)<br />
    control add imgbutton, hPIN_Dlg, %ID_PINCanx, "PINCanx", _<br />
     &nbsp;&nbsp;191 - (36 * RatioX), 75 + (16 * RatioY), (36 * RatioX), (36 * RatioY)<br />
  end if<br />
  '<br />
  dialog show modal hPIN_Dlg call  PINDlgCB to PIN<br />
  function = PIN<br />
end function<br />
'================================================================= callback ====<br />
callback function PINDlgCB() as long<br />
  static A_IsExposed, B_IsExposed as long<br />
  static PINStr as wstring<br />
  local TmpL as long<br />
  local TmpS as wstring<br />
  if cb.msg = %wm_command then<br />
    if cb.ctlmsg = %en_update then<br />
      if (cb.ctl &gt;= %ID_PINA1Txtbx) and (cb.ctl &lt;= %ID_PINB9Txtbx) then<br />
        if (gNumOfDigits - 1) &gt; (&amp;h00000F and cb.ctl) then<br />
          control set focus cb.hndl, cb.ctl + 1<br />
        else<br />
          control set focus cb.hndl, %ID_PINB1Txtbx<br />
        end if<br />
      end if<br />
    elseif cb.ctlmsg = %bn_clicked then<br />
      select case as const cb.ctl<br />
        case %ID_PINAExposeBtn<br />
          if A_IsExposed then 'unexpose<br />
            for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR,_<br />
               &nbsp;&nbsp;&amp;h2A, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINAExposeBtn, "ShowPWon24"<br />
            A_IsExposed = 0<br />
          else 'expose<br />
            for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR, 0, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINAExposeBtn, "ShowPWoff24"<br />
            A_IsExposed = -1<br />
          end if<br />
          for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
            control redraw cb.hndl, TmpL<br />
          next<br />
        case %ID_PINBExposeBtn<br />
          if B_IsExposed then<br />
            for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR,_<br />
               &nbsp;&nbsp;&amp;h2A, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINBExposeBtn, "ShowPWon24"<br />
            B_IsExposed = 0<br />
          else 'expose<br />
            for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR, 0, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINBExposeBtn, "ShowPWoff24"<br />
            B_IsExposed = -1<br />
          end if<br />
          for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
            control redraw cb.hndl, TmpL<br />
          next<br />
        '············································· submit single button ····<br />
        case %ID_PINSubmitSnglBtn, %ID_PINSubmitDuplBtn<br />
          control get text cb.hndl, %ID_PINA1Txtbx to TmpS<br />
          PINStr = TmpS<br />
          for TmpL = 1 to 8<br />
            control get text cb.hndl, %ID_PINA1Txtbx + TmpL to TmpS<br />
            PINStr += TmpS<br />
          next<br />
          TmpL = len(PINStr)<br />
          if gIsVariableDigits then<br />
            if Tmpl &lt; 4 then<br />
              msgbox "Varible length PINs must be 4 to 9 digits "&#36;&#36; + _<br />
                   &nbsp;&nbsp;"and exactly the same as when it was created."&#36;&#36;, _<br />
                   &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
              exit function<br />
            end if<br />
          else<br />
            if TmpL &lt; gNumOfDigits then<br />
              msgbox "The program using this PIN requires "&#36;&#36; + _<br />
                   &nbsp;&nbsp;dec&#36;(gNumOfDigits) + " digits."&#36;&#36;, _<br />
                   &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
              exit function<br />
            end if<br />
          end if<br />
          if cb.ctl = %ID_PINSubmitDuplBtn then<br />
            for TmpL = 0 to 8<br />
              control get text cb.hndl, %ID_PINB1Txtbx + TmpL to TmpS<br />
                if TmpS = mid&#36;(PINStr, TmpL + 1, 1) then<br />
                  iterate for<br />
                else<br />
                  msgbox "The and the repeat do not match."&#36;&#36;, _<br />
                       &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, _<br />
                       &nbsp;&nbsp;gEntryErrTitle<br />
                  exit function<br />
                end if<br />
              next<br />
          end if<br />
          if gIsVariableDigits then<br />
            TmpL = 9 - len(PINStr)<br />
            PINStr += string&#36;&#36;(TmpL, "0"&#36;&#36;)<br />
          end if<br />
          dialog end cb.hndl, val(PINStr)<br />
        case %ID_PINHelp<br />
       &nbsp;&nbsp;'' ShellExecute<br />
            ShellExecute (0, "open"&#36;&#36;, "PIN_Enter_Help.html", ""&#36;&#36;, ""&#36;&#36;, %sw_shownormal)<br />
        case %ID_PINCanx<br />
          goto NoPIN<br />
      end select<br />
    end if<br />
  elseif (lo(word, cb.wparam) = %sc_close) and (cb.msg = %wm_syscommand) then<br />
    goto NoPIN<br />
  end if<br />
  exit function<br />
  NoPIN:<br />
  TmpL = msgbox("""Yes"", to quit PIN entry."&#36;&#36; + &#36;&#36;crlf + _<br />
                """No"", to stay and enter a PIN."&#36;&#36;, _<br />
            %mb_yesno or %mb_iconquestion or %mb_defbutton2 or %mb_taskmodal, _<br />
            "Verify Quitting PIN Entry"&#36;&#36;)<br />
  if TmpL = %idno then<br />
    function = -1<br />
  else<br />
    dialog end cb.hndl<br />
  end if<br />
end function</code></div></div>Demo source: <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>'File PIN_SLL_demo.bas<br />
#compile exe<br />
#dim all<br />
#if %def(%pb_cc32)<br />
  #console off<br />
#endif<br />
declare function PIN_Enter lib "EnterPIN.dll" alias "PIN_Enter" _<br />
                                            (byval hParent as dword, _<br />
                                           &nbsp;&nbsp;byval DuplPIN as long, _<br />
                                           &nbsp;&nbsp;byval NumOfDigits as long) as dword<br />
function pbmain () as long<br />
  local hTWin, PIN as dword<br />
  local Rspnc as wstring<br />
  txt.window("PIN Enter Popup Demonstration"&#36;&#36;, 400, 70, 20, 75) to hTWin<br />
  txt.color = %rgb_green<br />
  txt.print "At any wait use any key to continue. (like now :) )"&#36;&#36;<br />
  txt.waitkey&#36;<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "A dual PIN entry with number of digits set to 4. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 1, 4), 4)"."&#36;&#36;<br />
  txt.color = %rgb_green<br />
  txt.print<br />
  txt.print "Any key to continue."<br />
  txt.waitkey&#36;<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "A single PIN entry with number of digits set to 4. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 4), 4)"."&#36;&#36;<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print """ESC"" to end demo, any other key to continue with next."<br />
  Rspnc = txt.waitkey&#36;<br />
  if Rspnc = &#36;&#36;esc then exit function<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "Number of PIN digits set to 9. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 9), 9)"."&#36;&#36;<br />
  txt.color = %rgb_blue<br />
  txt.print "You had to enter 9 digits, or ""Cancel PIN"" to get here."&#36;&#36;<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print """ESC"" to end demo, any other key to continue with next."<br />
  Rspnc = txt.waitkey&#36;<br />
  if Rspnc = &#36;&#36;esc then exit function<br />
  txt.color = %rgb_blue<br />
  txt.print "Number of PIN digits set to 0 (user preference). "&#36;&#36;<br />
  txt.print "Looks like previous, but 4 to 9 digits allowed."&#36;&#36;;<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 0), 9)"."&#36;&#36;<br />
  '<br />
<br />
  '---------------------------------------------------------------------<br />
  txt.color = %rgb_green<br />
  txt.print<br />
  txt.print "Any key will close."&#36;&#36;<br />
  txt.waitkey&#36;<br />
end function</code></div></div>]]></description>
			<content:encoded><![CDATA[A popup for user to enter a PIN for return to your app. The number of digits is specified in the call, and checked by the function in the DLL.<br />
<br />
Longer description<br />
at <a href="https://www.yarker-dsyc.info/Programs/Misc/PIN/Enter_PIN_DLL.html" target="_blank" rel="noopener" class="mycode_url">https://www.yarker-dsyc.info/Programs/Mi...N_DLL.html</a><br />
<br />
Source, compiled, icons and Help file in ZIP<br />
at <a href="https://www.yarker-dsyc.info/Programs/Misc/PIN/Enter_PIN.zip" target="_blank" rel="noopener" class="mycode_url">https://www.yarker-dsyc.info/Programs/Mi...er_PIN.zip</a><br />
<br />
DLL source: <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#compile dll<br />
#dim all<br />
'================================================================<br />
enum PIN_IDs singular<br />
  '%en_update group<br />
  ID_PINA1Txtbx = &amp;h3000&amp;<br />
  ID_PINA2Txtbx<br />
  ID_PINA3Txtbx<br />
  ID_PINA4Txtbx<br />
  ID_PINA5Txtbx<br />
  ID_PINA6Txtbx<br />
  ID_PINA7Txtbx<br />
  ID_PINA8Txtbx<br />
  ID_PINA9Txtbx<br />
  ID_PINB1Txtbx = &amp;h3010<br />
  ID_PINB2Txtbx<br />
  ID_PINB3Txtbx<br />
  ID_PINB4Txtbx<br />
  ID_PINB5Txtbx<br />
  ID_PINB6Txtbx<br />
  ID_PINB7Txtbx<br />
  ID_PINB8Txtbx<br />
  ID_PINB9Txtbx<br />
  '%bn_clicked group<br />
  ID_PINAExposeBtn<br />
  ID_PINBExposeBtn<br />
  ID_PINSubmitSnglBtn<br />
  ID_PINSubmitDuplBtn<br />
  ID_PINHelp<br />
  ID_PINCanx<br />
  'not selected in callback<br />
  ID_PINInstruLbl<br />
  ID_PINALbl<br />
  ID_PINBLbl                                    'type rect '<br />
end enum 'number up to &amp;h3FF reserved<br />
'<br />
%EM_SETPASSWORDCHAR = &amp;h00CC<br />
%wm_syscommand = &amp;h0112 '(not built into PBWin)<br />
%DT_CalcRect = &amp;h00000400<br />
#resource icon, PIN16, ".&#92;PIN16.ico"<br />
#resource icon, ShowPWon24, ".&#92;ShowPWon24.ico"<br />
#resource icon, ShowPWoff24, ".&#92;ShowPWoff24.ico"<br />
#resource icon, PINSubmit, ".&#92;PINSubmit48.ico"<br />
#resource icon, PINHelp, ".&#92;HelpQuesBtn48.ico"<br />
#resource icon, PINCanx, ".&#92;CancelPIN32.ico"<br />
global gIsVariableDigits, gNumOfDigits as long '(is in PIN_Enter and callback)<br />
global gEntryErrTitle as wstring<br />
declare function ShellExecute lib "Shell32.dll" alias "ShellExecuteW" ( _<br />
    byval hwnd as dword, lpOperation as wstringz, lpFile as wstringz, _<br />
    lpParameters as wstringz, lpDirectory as wstringz, byval nShowCmd as long) _<br />
    as dword<br />
<br />
'############################################################# the function ####<br />
function PIN_Enter alias "PIN_Enter" (byval hParent as dword, _<br />
                                      byval DualPIN as long, _<br />
                                      byval NumOfDigits as long) export as dword<br />
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<br />
  static Not1stCall, nFontMono14B as long<br />
  static gEntryErrTitle as wstring<br />
  static RatioX, RatioY as single<br />
  local hPIN_Dlg, PIN as dword<br />
  local TBY, TBX, ID_Dig, PosX as long<br />
  local InstruStr, DigCnt as wstring<br />
  '========================================================= initialization ====<br />
  '····························································· persistent ····<br />
  if Not1stCall = 0 then 'so it is first call<br />
    Not1stCall = -1<br />
    font new "Lucida Console", 14, 1, 1, 0, 0 to nFontMono14B<br />
    dialog default font "Segoe UI", 12, 0, 1<br />
    gEntryErrTitle = "PIN Entry Error"&#36;&#36;<br />
  end if<br />
  '······························································ each call ····<br />
  if (NumOfDigits &lt; 0) or (NumOfDigits &gt; 9) then 'check range<br />
    msgbox "The number of PIN digits can only be optionally"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"not used, or 0 to 9 digits long."&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"Not used or 0 is for a variable length PIN of"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"1 to 9 digigits. Otherwise the number of digits is"&#36;&#36; + &#36;&#36;crlf + _<br />
         &nbsp;&nbsp;"fixed by the using program."&#36;&#36;, _<br />
         &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
    exit function<br />
  end if<br />
  if NumOfDigits = 0 then 'variable number<br />
    gIsVariableDigits = -1<br />
    gNumOfDigits = 9<br />
  else<br />
    gNumOfDigits = NumOfDigits<br />
  end if<br />
  '================================================================= dialog ====<br />
  dialog new hParent, "Enter PIN."&#36;&#36;, _<br />
      0, 10, 200, 120, _<br />
   &nbsp;&nbsp;%ds_3dlook or %ds_modalframe or %ds_nofailcreate or %ds_setfont or _<br />
   &nbsp;&nbsp;%ws_caption or %ws_clipsiblings or %ws_dlgframe or %ws_popup or _<br />
   &nbsp;&nbsp;%ws_sysmenu, %ws_ex_left or %ws_ex_ltrreading to hPIN_Dlg<br />
  dialog set icon hPIN_Dlg, "PIN16"<br />
  '------------------------------------------------------- unit/pixel ratio ----<br />
  #if %pb_revision = &amp;h1004<br />
    dialog units hPIN_Dlg, 1000, 1000 to pixels TBY, TBX 'precycle longs<br />
  #else<br />
    dialog units hPIN_Dlg, 1000, 1000 to pixels TBX, TBY<br />
  #endif<br />
  RatioX = 1000 /TBX : RatioY =  1000 / TBY 'mult img px for button units<br />
  '------------------------------------------------------------- PIN instru ----<br />
  if DualPIN then<br />
    InstruStr = "The application requires dual entry for the requested "&#36;&#36; + _<br />
                "task. "&#36;&#36;<br />
  end if<br />
  if NumOfDigits then<br />
    InstruStr +="Enter the "&#36;&#36; + dec&#36;(gNumOfDigits) + " digit PIN. "&#36;&#36;<br />
  else<br />
    InstruStr += "The number of digits is not fixed. The PIN may be 4 "&#36;&#36; + _<br />
               &nbsp;&nbsp;"to 9 digits. Leave unused digits at right empty. "&#36;&#36;<br />
  end if<br />
  InstruStr += "The only characters allowed are ""0"" to ""9""."&#36;&#36;<br />
  control add label, hPIN_Dlg, %ID_PINInstruLbl, InstruStr,  _<br />
   &nbsp;&nbsp;5, 4, 185, 34, %ss_left, %ws_ex_left<br />
  control set color hPIN_Dlg, %ID_PINInstruLbl, -1, &amp;hFAFAFA<br />
  '---------------------------------------------------- "A" digit textboxes ----<br />
  control add label, hPIN_Dlg, %ID_PINALbl, "Enter PIN:"&#36;&#36;, _<br />
   &nbsp;&nbsp;4, 45, 42, 10, %ss_right, %ws_ex_left &nbsp;&nbsp;''55<br />
  '<br />
  PosX = 49<br />
  for ID_Dig = %ID_PINA1Txtbx to %ID_PINA1Txtbx + gNumOfDigits - 1<br />
    control add textbox, hPIN_Dlg, ID_Dig, ""&#36;&#36;, _<br />
     &nbsp;&nbsp;PosX, 44, 12, 10, %es_center or %es_number or %ws_border or _<br />
     &nbsp;&nbsp;%ws_tabstop or %es_password, %ws_ex_clientedge or %ws_ex_left<br />
    control set font hPIN_Dlg, ID_Dig, nFontMono14B<br />
    PosX += 15<br />
  next<br />
  '<br />
  control add imgbutton, hPIN_Dlg, %ID_PINAExposeBtn, "ShowPWon24", _<br />
   &nbsp;&nbsp;181, 43, 28 * RatioX, 28 * RatioY<br />
  if DualPIN = 0 then<br />
    control add imgbutton, hPIN_Dlg, %ID_PINSubmitSnglBtn, "PINSubmit", _<br />
     &nbsp;&nbsp;49 - (52 * RatioX), 59, 52 * RatioX, 52 * RatioY<br />
 &nbsp;&nbsp;' dialog set size hPIN_Dlg, 200, 75 + (52 * RatioY)<br />
  else<br />
  '---------------------------------------------------- "B" digit textboxes ----<br />
    PosX = 49<br />
    control add label, hPIN_Dlg, %ID_PINBLbl, "Reenter PIN:"&#36;&#36;, _<br />
     &nbsp;&nbsp;4, 60, 42, 10, %ss_right, %ws_ex_left &nbsp;&nbsp;''55<br />
    for ID_Dig = %ID_PINB1Txtbx to %ID_PINB1Txtbx + gNumOfDigits - 1<br />
      control add textbox, hPIN_Dlg, ID_Dig, ""&#36;&#36;, _<br />
       &nbsp;&nbsp;PosX, 60, 12, 10, %es_center or %es_number or %ws_border or _<br />
       &nbsp;&nbsp;%ws_tabstop or %es_password, %ws_ex_clientedge or %ws_ex_left<br />
      control set font hPIN_Dlg, ID_Dig, nFontMono14B<br />
      PosX += 15<br />
    next<br />
  '<br />
    control add imgbutton, hPIN_Dlg, %ID_PINBExposeBtn, "ShowPWon24", _<br />
     &nbsp;&nbsp;181, 59, 28 * RatioX, 28 * RatioY<br />
    control add imgbutton, hPIN_Dlg, %ID_PINSubmitDuplBtn, "PINSubmit", _<br />
     &nbsp;&nbsp;49 - (52 * RatioX), 75, 52 * RatioX, 52 * RatioY<br />
  end if<br />
  '----------------------------------------------------- "A" and "B" common ----<br />
  if DualPIN = 0 then<br />
    control add imgbutton, hPIN_Dlg, %ID_PINHelp, "PINHelp", _<br />
     &nbsp;&nbsp;191 - (99 * RatioX), 59, 52 * RatioX, 52 * RatioY<br />
    control add imgbutton, hPIN_Dlg, %ID_PINCanx, "PINCanx", _<br />
     &nbsp;&nbsp;191 - (36 * RatioX), 59 + (16 * RatioY), (36 * RatioX), (36 * RatioY)<br />
    dialog set size hPIN_Dlg, 200, 76 + (52 * RatioY)<br />
  else<br />
    control add imgbutton, hPIN_Dlg, %ID_PINHelp, "PINHelp", _<br />
     &nbsp;&nbsp;191 - (99 * RatioX), 75, 52 * RatioX, 52 * RatioY<br />
<br />
    dialog set size hPIN_Dlg, 200, 92 + (52 * RatioY)<br />
    control add imgbutton, hPIN_Dlg, %ID_PINCanx, "PINCanx", _<br />
     &nbsp;&nbsp;191 - (36 * RatioX), 75 + (16 * RatioY), (36 * RatioX), (36 * RatioY)<br />
  end if<br />
  '<br />
  dialog show modal hPIN_Dlg call  PINDlgCB to PIN<br />
  function = PIN<br />
end function<br />
'================================================================= callback ====<br />
callback function PINDlgCB() as long<br />
  static A_IsExposed, B_IsExposed as long<br />
  static PINStr as wstring<br />
  local TmpL as long<br />
  local TmpS as wstring<br />
  if cb.msg = %wm_command then<br />
    if cb.ctlmsg = %en_update then<br />
      if (cb.ctl &gt;= %ID_PINA1Txtbx) and (cb.ctl &lt;= %ID_PINB9Txtbx) then<br />
        if (gNumOfDigits - 1) &gt; (&amp;h00000F and cb.ctl) then<br />
          control set focus cb.hndl, cb.ctl + 1<br />
        else<br />
          control set focus cb.hndl, %ID_PINB1Txtbx<br />
        end if<br />
      end if<br />
    elseif cb.ctlmsg = %bn_clicked then<br />
      select case as const cb.ctl<br />
        case %ID_PINAExposeBtn<br />
          if A_IsExposed then 'unexpose<br />
            for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR,_<br />
               &nbsp;&nbsp;&amp;h2A, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINAExposeBtn, "ShowPWon24"<br />
            A_IsExposed = 0<br />
          else 'expose<br />
            for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR, 0, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINAExposeBtn, "ShowPWoff24"<br />
            A_IsExposed = -1<br />
          end if<br />
          for TmpL = %ID_PINA1Txtbx to %ID_PINA9Txtbx<br />
            control redraw cb.hndl, TmpL<br />
          next<br />
        case %ID_PINBExposeBtn<br />
          if B_IsExposed then<br />
            for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR,_<br />
               &nbsp;&nbsp;&amp;h2A, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINBExposeBtn, "ShowPWon24"<br />
            B_IsExposed = 0<br />
          else 'expose<br />
            for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
              control send cb.hndl, TmpL, %EM_SETPASSWORDCHAR, 0, 0<br />
            next<br />
            control set imgbutton cb.hndl, %ID_PINBExposeBtn, "ShowPWoff24"<br />
            B_IsExposed = -1<br />
          end if<br />
          for TmpL = %ID_PINB1Txtbx to %ID_PINB9Txtbx<br />
            control redraw cb.hndl, TmpL<br />
          next<br />
        '············································· submit single button ····<br />
        case %ID_PINSubmitSnglBtn, %ID_PINSubmitDuplBtn<br />
          control get text cb.hndl, %ID_PINA1Txtbx to TmpS<br />
          PINStr = TmpS<br />
          for TmpL = 1 to 8<br />
            control get text cb.hndl, %ID_PINA1Txtbx + TmpL to TmpS<br />
            PINStr += TmpS<br />
          next<br />
          TmpL = len(PINStr)<br />
          if gIsVariableDigits then<br />
            if Tmpl &lt; 4 then<br />
              msgbox "Varible length PINs must be 4 to 9 digits "&#36;&#36; + _<br />
                   &nbsp;&nbsp;"and exactly the same as when it was created."&#36;&#36;, _<br />
                   &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
              exit function<br />
            end if<br />
          else<br />
            if TmpL &lt; gNumOfDigits then<br />
              msgbox "The program using this PIN requires "&#36;&#36; + _<br />
                   &nbsp;&nbsp;dec&#36;(gNumOfDigits) + " digits."&#36;&#36;, _<br />
                   &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, gEntryErrTitle<br />
              exit function<br />
            end if<br />
          end if<br />
          if cb.ctl = %ID_PINSubmitDuplBtn then<br />
            for TmpL = 0 to 8<br />
              control get text cb.hndl, %ID_PINB1Txtbx + TmpL to TmpS<br />
                if TmpS = mid&#36;(PINStr, TmpL + 1, 1) then<br />
                  iterate for<br />
                else<br />
                  msgbox "The and the repeat do not match."&#36;&#36;, _<br />
                       &nbsp;&nbsp;%mb_ok or %mb_iconerror or %mb_taskmodal, _<br />
                       &nbsp;&nbsp;gEntryErrTitle<br />
                  exit function<br />
                end if<br />
              next<br />
          end if<br />
          if gIsVariableDigits then<br />
            TmpL = 9 - len(PINStr)<br />
            PINStr += string&#36;&#36;(TmpL, "0"&#36;&#36;)<br />
          end if<br />
          dialog end cb.hndl, val(PINStr)<br />
        case %ID_PINHelp<br />
       &nbsp;&nbsp;'' ShellExecute<br />
            ShellExecute (0, "open"&#36;&#36;, "PIN_Enter_Help.html", ""&#36;&#36;, ""&#36;&#36;, %sw_shownormal)<br />
        case %ID_PINCanx<br />
          goto NoPIN<br />
      end select<br />
    end if<br />
  elseif (lo(word, cb.wparam) = %sc_close) and (cb.msg = %wm_syscommand) then<br />
    goto NoPIN<br />
  end if<br />
  exit function<br />
  NoPIN:<br />
  TmpL = msgbox("""Yes"", to quit PIN entry."&#36;&#36; + &#36;&#36;crlf + _<br />
                """No"", to stay and enter a PIN."&#36;&#36;, _<br />
            %mb_yesno or %mb_iconquestion or %mb_defbutton2 or %mb_taskmodal, _<br />
            "Verify Quitting PIN Entry"&#36;&#36;)<br />
  if TmpL = %idno then<br />
    function = -1<br />
  else<br />
    dialog end cb.hndl<br />
  end if<br />
end function</code></div></div>Demo source: <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>'File PIN_SLL_demo.bas<br />
#compile exe<br />
#dim all<br />
#if %def(%pb_cc32)<br />
  #console off<br />
#endif<br />
declare function PIN_Enter lib "EnterPIN.dll" alias "PIN_Enter" _<br />
                                            (byval hParent as dword, _<br />
                                           &nbsp;&nbsp;byval DuplPIN as long, _<br />
                                           &nbsp;&nbsp;byval NumOfDigits as long) as dword<br />
function pbmain () as long<br />
  local hTWin, PIN as dword<br />
  local Rspnc as wstring<br />
  txt.window("PIN Enter Popup Demonstration"&#36;&#36;, 400, 70, 20, 75) to hTWin<br />
  txt.color = %rgb_green<br />
  txt.print "At any wait use any key to continue. (like now :) )"&#36;&#36;<br />
  txt.waitkey&#36;<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "A dual PIN entry with number of digits set to 4. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 1, 4), 4)"."&#36;&#36;<br />
  txt.color = %rgb_green<br />
  txt.print<br />
  txt.print "Any key to continue."<br />
  txt.waitkey&#36;<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "A single PIN entry with number of digits set to 4. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 4), 4)"."&#36;&#36;<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print """ESC"" to end demo, any other key to continue with next."<br />
  Rspnc = txt.waitkey&#36;<br />
  if Rspnc = &#36;&#36;esc then exit function<br />
  '<br />
  txt.color = %rgb_blue<br />
  txt.print "Number of PIN digits set to 9. "&#36;&#36;;<br />
  txt.color = %rgb_black<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 9), 9)"."&#36;&#36;<br />
  txt.color = %rgb_blue<br />
  txt.print "You had to enter 9 digits, or ""Cancel PIN"" to get here."&#36;&#36;<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print """ESC"" to end demo, any other key to continue with next."<br />
  Rspnc = txt.waitkey&#36;<br />
  if Rspnc = &#36;&#36;esc then exit function<br />
  txt.color = %rgb_blue<br />
  txt.print "Number of PIN digits set to 0 (user preference). "&#36;&#36;<br />
  txt.print "Looks like previous, but 4 to 9 digits allowed."&#36;&#36;;<br />
  txt.print "Returned PIN is: "&#36;&#36; + dec&#36;(PIN_Enter(hTWin, 0, 0), 9)"."&#36;&#36;<br />
  '<br />
<br />
  '---------------------------------------------------------------------<br />
  txt.color = %rgb_green<br />
  txt.print<br />
  txt.print "Any key will close."&#36;&#36;<br />
  txt.waitkey&#36;<br />
end function</code></div></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Announcements for updates]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=125</link>
			<pubDate>Mon, 13 Apr 2026 14:16:56 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=71">Juergen Kuehlwein</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=125</guid>
			<description><![CDATA[There is an improved version of the experimental code converter for JKB (JKB_Convert.exe), please download the update package (update.zip) and unpack over your existing installation.]]></description>
			<content:encoded><![CDATA[There is an improved version of the experimental code converter for JKB (JKB_Convert.exe), please download the update package (update.zip) and unpack over your existing installation.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Sounds good!]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=124</link>
			<pubDate>Mon, 13 Apr 2026 00:54:44 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=23">Dale Yarker</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=124</guid>
			<description><![CDATA[From: <span style="font-weight: bold;" class="mycode_b">What´s different</span><br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>The syntax is (with some minor restrictions) compatible to PowerBASIC. These restrictions are:</blockquote>
The bit that caught my interest<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>- Variables must not be declared with "DIM" anymore! ...  Dim is exclusively used for dimensioning arrays. </blockquote>
 Big agreement and self-imposed in my code.<br />
<br />
   <br />
<blockquote class="mycode_quote"><cite>Quote:</cite>THREADED is not supported ATM.</blockquote>
Aww, when thread is needed it is needed. Since I seldom need it its not a big handicap for now.<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>- You may still declare multiple variables of the same data type in one single line. "LOCAL a, b, c AS LONG" is accepted. "LOCAL a&#36;, b AS DWORD, c AS LONG" throws an error, because a&#36;, b and c represent different data types.</blockquote>
Also self-imposed.<br />
<br />
I'll download now.  <img src="http://pump.richheimer.de/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /> I need to get closer to the bottom of "job jar" to try it.  <img src="http://pump.richheimer.de/images/smilies/sad.png" alt="Sad" title="Sad" class="smilie smilie_8" />]]></description>
			<content:encoded><![CDATA[From: <span style="font-weight: bold;" class="mycode_b">What´s different</span><br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>The syntax is (with some minor restrictions) compatible to PowerBASIC. These restrictions are:</blockquote>
The bit that caught my interest<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>- Variables must not be declared with "DIM" anymore! ...  Dim is exclusively used for dimensioning arrays. </blockquote>
 Big agreement and self-imposed in my code.<br />
<br />
   <br />
<blockquote class="mycode_quote"><cite>Quote:</cite>THREADED is not supported ATM.</blockquote>
Aww, when thread is needed it is needed. Since I seldom need it its not a big handicap for now.<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite>- You may still declare multiple variables of the same data type in one single line. "LOCAL a, b, c AS LONG" is accepted. "LOCAL a&#36;, b AS DWORD, c AS LONG" throws an error, because a&#36;, b and c represent different data types.</blockquote>
Also self-imposed.<br />
<br />
I'll download now.  <img src="http://pump.richheimer.de/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /> I need to get closer to the bottom of "job jar" to try it.  <img src="http://pump.richheimer.de/images/smilies/sad.png" alt="Sad" title="Sad" class="smilie smilie_8" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[What is different]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=123</link>
			<pubDate>Sun, 12 Apr 2026 12:43:52 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=71">Juergen Kuehlwein</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=123</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">What´s different</span><br />
<br />
The syntax is (with some minor restrictions) compatible to PowerBASIC. These restrictions are:<br />
<br />
<br />
- Variables must not be declared with "DIM" anymore! <br />
    LOCAL, GLOBAL, STATIC, INSTANCE or COMMON is required (= #DIM ALL in PB)!. Dim is exclusively used for dimensioning arrays. THREADED is not supported ATM.<br />
<br />
- You may still declare multiple variables of the same data type in one single line. "LOCAL a, b, c AS LONG" is accepted. "LOCAL a&#36;, b AS DWORD, c AS LONG" throws an error, because a&#36;, b and c represent different data types.<br />
<br />
<br />
- You may assign an intial value, e.g. "LOCAL x AS LONG = -1"<br />
<br />
<br />
- With variables you cannot have type specifiers anymore except for "&#36;" (dynamic ANSI string) or "&#36;&#36;" (dynamic wide string)<br />
<br />
<br />
- There are new data types: QWORD (unsigned 64 bit integer), SBYTE (signed 8 bit integer), XWORD (DWORD in 32 bit and QWORD in 64), XLONG (LONG in 32 bit and QUAD in 64)<br />
<br />
<br />
- Assembler code:   <br />
    ! cmp byte [esi], 0  -&gt; byte ptr (the key word "ptr" is mandatory, assembler error otherwise)<br />
    ! ret must become,  ! retn, (ret ends a stackframe)<br />
<br />
    !.if (eax == 0)<br />
    ! ... "<br />
    !.endif                     (MASM Hi-level syntax is possible)<br />
<br />
    XAX = EAX in 32 bit and RAX in 64 bit<br />
<br />
<br />
- Reserved words: there is a list of words, which are forbidden as variable or procedure names, eg. pos, count, enter, comment et. al<br />
<br />
<br />
- String expressions: no logical string expressions, but automatic build&#36;<br />
    e.g.        if a&#36; &lt; b&#36; and c&#36; &lt; d&#36; then<br />
                 ...<br />
            <br />
    must be    if a&#36; &lt; b&#36; then<br />
                      if c&#36; &lt; d&#36; then<br />
                      ...<br />
              <br />
    but a&#36; + b&#36; + c&#36;, is always compiled as BUILD&#36;(a&#36;, b&#36;, c&#36;), BUILD&#36; is valid syntax, but it is not necessary anymore              <br />
<br />
<br />
<br />
- Conditional compiling: code inside conditional compiling blocks (even if condition is not met) must be compilable<br />
    you cannot code anymore:<br />
    #IF 0<br />
    &lt;your comments here&gt; -&gt; you must pepend an apostrophe to make it a comment<br />
    #ENDIF<br />
<br />
<br />
#TRACE, #PROFILE and #CALLSTACK make use of the OutputDebugString Viewer, this is still experimental<br />
<br />
<br />
- Syntax:<br />
PARSE        (no special treatment for default separator "," and quotes)<br />
<br />
ISTRUE      (parenthesis are required, it´s a function not an operator)<br />
ISFALSE      (parenthesis are required, it´s a function not an operator)<br />
<br />
FORMAT&#36;      (only one formatting mask allowed)<br />
JOIN&#36;        (without BINARY option and special quote handling)<br />
PARSE&#36;      (without BINARY option and special quote handling)<br />
<br />
PRINT        (requires sparator (, ; spc() tab()) between expressions)<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">What´s new:</span><br />
<br />
#SEH - in case of a GPF, the offending line is shown in the IDE<br />
<br />
TIMING [END]  -  return elapsed time in µs, syntax: TIMING [END] qword/quadvar<br />
ISVALID(&lt;ptr&gt;) -  returns -1, if pointer points to valid memory, 0 otherwise<br />
<br />
SIN            -  y = SIN([deg/rad], x) default is deg, applies to all trigonometric functions<br />
<br />
ZIP:                                                                                  'zip into ziparchive<br />
' ZIP string s&#36;, filename (in ziparchive), ziparchive [, password] [, call callback]<br />
' ZIP filename(s), ziparchive [, password] [, call callback]<br />
' ZIP memory ptr, len, filename (in ziparchive), ziparchive [, password] [, call callback]<br />
ZIP&#36;:                                                                                  'zip into string<br />
' z&#36; = ZIP&#36;(string s&#36;, filename (in archive) [, password] [size = x] [, call callback]) <br />
' z&#36; = ZIP&#36;(filename(s) [, password] [size = x] [, call callback]) <br />
' z&#36; = ZIP&#36;(memory ptr, len, filename (in archive) [, password] [size = x] [, call callback]) <br />
UNZIP:                                                                                'unzip ziparchive<br />
' UNZIP filename(s) (in string), string s&#36; [, password] [to folder] [, call callback]<br />
' UNZIP filename(s) (in ziparchive), ziparchive [, password] [to folder] [, call callback]<br />
' UNZIP filename(s) (in memory), memory ptr, len [, password] [to folder] [, call callback]<br />
UNZIP&#36;                                                                                'unzip into string<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in string), string z&#36;|ziparchive] [, password])<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in ziparchive), ziparchive] [, password])<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in memory), memory ptr, len|ziparchive] [, password])<br />
ZIPINFO:                                                                              'return # of files in zip + array of zipinfo<br />
' x = ZIPINFO(array, string z&#36;|ziparchive [, password])            <br />
' x = ZIPINFO(array, memory ptr, len|ziparchive [, password])<br />
ZIPCALC:                                                                              'return # of bytes for zipped data<br />
' x = ZIPCALC(string s&#36;|filename(s))<br />
' x = ZIPCALC memory ptr, len|filename(s)<br />
UNZIPCALC:                                                                            'return # of bytes for unzipped data<br />
' x = UNZIPCALC( filename(s), string z&#36;|ziparchive [, password])<br />
' x = UNZIPCALC( filename(s), memory pointer, len|ziparchive [, password])<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Run 32 bit code:</span><br />
As a first step try to run 32 bit code. Please adapt your code according to the above restrictions. If there are many places to adapt, the Replace Dialog (Ctrl + R) is your friend. The first line must be "#COMPILER JKB [32]", "F9" compiles and executes. The IDE will complain about errors.<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Run 64 bit code:</span><br />
64 bit code definitely needs adaptions: all pointers and handles (which are pointers in fact) must become 64 bit data types (DWORD -&gt; XWORD and LONG -&gt; XLONG). The first line must be "#COMPILER JKB 64". <br />
<br />
<br />
<br />
There is a (still experimental) code converter (Credits to Norbert Spoerl for supplying ideas and major parts of code) for adapting existing code to the new requirements. You may use the menu (last item in "File" menu: "Prepare Source for JKB" ) or the top toolbar (a new button, next to the "command prompt" button on the right side). This feature is applied to current file in the IDE. A copy (&lt;name&gt;.original) is made before. Yet you may still have to adapt some things manually.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please don´t post in this thread, feel free to ask questions in "Discussions" thread</span>]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">What´s different</span><br />
<br />
The syntax is (with some minor restrictions) compatible to PowerBASIC. These restrictions are:<br />
<br />
<br />
- Variables must not be declared with "DIM" anymore! <br />
    LOCAL, GLOBAL, STATIC, INSTANCE or COMMON is required (= #DIM ALL in PB)!. Dim is exclusively used for dimensioning arrays. THREADED is not supported ATM.<br />
<br />
- You may still declare multiple variables of the same data type in one single line. "LOCAL a, b, c AS LONG" is accepted. "LOCAL a&#36;, b AS DWORD, c AS LONG" throws an error, because a&#36;, b and c represent different data types.<br />
<br />
<br />
- You may assign an intial value, e.g. "LOCAL x AS LONG = -1"<br />
<br />
<br />
- With variables you cannot have type specifiers anymore except for "&#36;" (dynamic ANSI string) or "&#36;&#36;" (dynamic wide string)<br />
<br />
<br />
- There are new data types: QWORD (unsigned 64 bit integer), SBYTE (signed 8 bit integer), XWORD (DWORD in 32 bit and QWORD in 64), XLONG (LONG in 32 bit and QUAD in 64)<br />
<br />
<br />
- Assembler code:   <br />
    ! cmp byte [esi], 0  -&gt; byte ptr (the key word "ptr" is mandatory, assembler error otherwise)<br />
    ! ret must become,  ! retn, (ret ends a stackframe)<br />
<br />
    !.if (eax == 0)<br />
    ! ... "<br />
    !.endif                     (MASM Hi-level syntax is possible)<br />
<br />
    XAX = EAX in 32 bit and RAX in 64 bit<br />
<br />
<br />
- Reserved words: there is a list of words, which are forbidden as variable or procedure names, eg. pos, count, enter, comment et. al<br />
<br />
<br />
- String expressions: no logical string expressions, but automatic build&#36;<br />
    e.g.        if a&#36; &lt; b&#36; and c&#36; &lt; d&#36; then<br />
                 ...<br />
            <br />
    must be    if a&#36; &lt; b&#36; then<br />
                      if c&#36; &lt; d&#36; then<br />
                      ...<br />
              <br />
    but a&#36; + b&#36; + c&#36;, is always compiled as BUILD&#36;(a&#36;, b&#36;, c&#36;), BUILD&#36; is valid syntax, but it is not necessary anymore              <br />
<br />
<br />
<br />
- Conditional compiling: code inside conditional compiling blocks (even if condition is not met) must be compilable<br />
    you cannot code anymore:<br />
    #IF 0<br />
    &lt;your comments here&gt; -&gt; you must pepend an apostrophe to make it a comment<br />
    #ENDIF<br />
<br />
<br />
#TRACE, #PROFILE and #CALLSTACK make use of the OutputDebugString Viewer, this is still experimental<br />
<br />
<br />
- Syntax:<br />
PARSE        (no special treatment for default separator "," and quotes)<br />
<br />
ISTRUE      (parenthesis are required, it´s a function not an operator)<br />
ISFALSE      (parenthesis are required, it´s a function not an operator)<br />
<br />
FORMAT&#36;      (only one formatting mask allowed)<br />
JOIN&#36;        (without BINARY option and special quote handling)<br />
PARSE&#36;      (without BINARY option and special quote handling)<br />
<br />
PRINT        (requires sparator (, ; spc() tab()) between expressions)<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">What´s new:</span><br />
<br />
#SEH - in case of a GPF, the offending line is shown in the IDE<br />
<br />
TIMING [END]  -  return elapsed time in µs, syntax: TIMING [END] qword/quadvar<br />
ISVALID(&lt;ptr&gt;) -  returns -1, if pointer points to valid memory, 0 otherwise<br />
<br />
SIN            -  y = SIN([deg/rad], x) default is deg, applies to all trigonometric functions<br />
<br />
ZIP:                                                                                  'zip into ziparchive<br />
' ZIP string s&#36;, filename (in ziparchive), ziparchive [, password] [, call callback]<br />
' ZIP filename(s), ziparchive [, password] [, call callback]<br />
' ZIP memory ptr, len, filename (in ziparchive), ziparchive [, password] [, call callback]<br />
ZIP&#36;:                                                                                  'zip into string<br />
' z&#36; = ZIP&#36;(string s&#36;, filename (in archive) [, password] [size = x] [, call callback]) <br />
' z&#36; = ZIP&#36;(filename(s) [, password] [size = x] [, call callback]) <br />
' z&#36; = ZIP&#36;(memory ptr, len, filename (in archive) [, password] [size = x] [, call callback]) <br />
UNZIP:                                                                                'unzip ziparchive<br />
' UNZIP filename(s) (in string), string s&#36; [, password] [to folder] [, call callback]<br />
' UNZIP filename(s) (in ziparchive), ziparchive [, password] [to folder] [, call callback]<br />
' UNZIP filename(s) (in memory), memory ptr, len [, password] [to folder] [, call callback]<br />
UNZIP&#36;                                                                                'unzip into string<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in string), string z&#36;|ziparchive] [, password])<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in ziparchive), ziparchive] [, password])<br />
' s&#36;(&#36;) = UNZIP&#36;(filename (in memory), memory ptr, len|ziparchive] [, password])<br />
ZIPINFO:                                                                              'return # of files in zip + array of zipinfo<br />
' x = ZIPINFO(array, string z&#36;|ziparchive [, password])            <br />
' x = ZIPINFO(array, memory ptr, len|ziparchive [, password])<br />
ZIPCALC:                                                                              'return # of bytes for zipped data<br />
' x = ZIPCALC(string s&#36;|filename(s))<br />
' x = ZIPCALC memory ptr, len|filename(s)<br />
UNZIPCALC:                                                                            'return # of bytes for unzipped data<br />
' x = UNZIPCALC( filename(s), string z&#36;|ziparchive [, password])<br />
' x = UNZIPCALC( filename(s), memory pointer, len|ziparchive [, password])<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Run 32 bit code:</span><br />
As a first step try to run 32 bit code. Please adapt your code according to the above restrictions. If there are many places to adapt, the Replace Dialog (Ctrl + R) is your friend. The first line must be "#COMPILER JKB [32]", "F9" compiles and executes. The IDE will complain about errors.<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Run 64 bit code:</span><br />
64 bit code definitely needs adaptions: all pointers and handles (which are pointers in fact) must become 64 bit data types (DWORD -&gt; XWORD and LONG -&gt; XLONG). The first line must be "#COMPILER JKB 64". <br />
<br />
<br />
<br />
There is a (still experimental) code converter (Credits to Norbert Spoerl for supplying ideas and major parts of code) for adapting existing code to the new requirements. You may use the menu (last item in "File" menu: "Prepare Source for JKB" ) or the top toolbar (a new button, next to the "command prompt" button on the right side). This feature is applied to current file in the IDE. A copy (&lt;name&gt;.original) is made before. Yet you may still have to adapt some things manually.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please don´t post in this thread, feel free to ask questions in "Discussions" thread</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Discussions]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=122</link>
			<pubDate>Sun, 12 Apr 2026 12:09:47 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=71">Juergen Kuehlwein</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=122</guid>
			<description><![CDATA[Please use this thread for asking all kinds of questions!]]></description>
			<content:encoded><![CDATA[Please use this thread for asking all kinds of questions!]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How to run own code]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=121</link>
			<pubDate>Sun, 12 Apr 2026 12:08:13 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=71">Juergen Kuehlwein</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=121</guid>
			<description><![CDATA[My IDE makes extensive use of hot keys, type CTRL + H for a list of key combinations<br />
<br />
In the IDE´s folder there is a file (list of available features.txt) listing all currently supported statements. Most statements are compatible to PB syntax<br />
<br />
I´m not absolutely sure, if my implementation of macros works correct under all circumstances, the same applies to math functions and all kinds of expressions, especially with new data types like QWORD and SBYTE. I am sure there will be bugs, issues and problems i didn´t find yet!<br />
<br />
<br />
Compiling the same code for 32 and 64 bit requires a special data type, which represents 32 bit in 32 bit and 64 bit in 64 bit: XWORD (unsigned) and XLONG (signed). Therefore all include files (i used José´s) must be prepared for this. Currently not all but about 2/3 have been translated and can be found in \Basic\Include_new.<br />
<br />
64 bit code is much more picky about alignment, 64 bit code refuses to work, if structure alignment is not correct. This produces hard to find errors, and i´m not sure if all structures have been translated properly for 64 bit.<br />
<br />
Inline assembler works as usual, i build ebp/rbp based stackframes and you can use PUSH and POP as usual, but in 64 bit code the stack pointer (rsp) must be 16 byte aligned before calls, otherwise you will experience all kinds of crashes. You may replace e/r by x for registers in order to write code, which compiles in 32 and 64 bit. Internally xax becomes eax in 32 bit and rax in 64 bit, this applies to all standard 32 bit registers (eax, ebx, ecx, edx, esi, edi, ebp, esp), obviously you cannot use r8 - r15 in 32 bit code.<br />
<br />
<br />
In 32 bit code the constant %x32_code and in 64 bit code %x64_code are predefined, so you can build conditional compiling blocks like:<br />
<br />
#ifdef %x64_code<br />
<br />
... 64 bit code goes here (must be compilable)<br />
<br />
#else<br />
<br />
... 32 bit code goes here (must be compilable)<br />
<br />
#endif<br />
<br />
<br />
While PowerBASIC allows for (variable)names like "cx" or "si", which are valid register names, my implementation currently doesn´t. So you must use different names. ATM there are some more words (in addition to language keywords), which are forbidden. You will get an error message in such cases.<br />
<br />
<br />
My object and COM implementation may need improvement, the focus was on being able to use COM services, which seems to work.Writing COM servers is possible but with some restrictions. Inheritance and multiple interfaces are not handled absolutely correct, i fear. There is nothing like #TLIB and "ME." (an object calling itself) doesn´t work yet.<br />
I want better error reporting, in many places you will get a simple "syntax error". It is possible to have more specific messages and i plan to do that, but it is not on top of my priority list.<br />
<br />
<br />
There are many ways of improving and optimizing my code, but for the moment the most important thing is making the "core" things stable.<br />
<br />
Then will be the time to add more features, currently it supports, what i would call the "core" features of a BASIC language. Feel free to ask for "core" features i might have missed. But i won´t add more or less "special" things, before the core can be considered actually stable. At the current point of development i must thoroughly test, what i have in order to avoid changes in the core functionality later on. Code generation must cover different scenarios, the currently supported feature set covers all these scenarios in (hopefully) all it´s aspects. So it should be suited for testing and finding bugs i missed. Further development will then be a variation or implementation of the existing core of code.<br />
<br />
E.g when passing arguments, such an argument can be: a literal, a constant, a variable, an array (as a whole, or as one single element), a structure (as a whole, or as one member of it), nested structures, a pointer, a resolved pointer, procedure returns, intrinsic functions (results from key words) and combinations and expressions of all of this. An argument can be passed "byref", "byval" and "bycopy". So there is a variety of possibilities, which must be taken care of.<br />
<br />
The most simple code for own tests would be:<br />
<br />
Code Select<br />
Code:<br />
#COMPILER JKB 32<br />
#COMPILE EXE<br />
<br />
FUNCTION MAIN<br />
<br />
...<br />
<br />
END FUNCTION<br />
<br />
<br />
Now you can fill in the body of MAIN (for convenience PBMAIN is also possible) with declarations of variables and code using the syntax known form PB. You can add subs and functions as usual. You may add "#INCLUDE "Win32Api.inc" for access to predefined constants and the Windows API.<br />
<br />
About 2/3 of José´s include files are already adapted to work in 64 bit Windows. There might still be issues though<br />
<br />
<br />
"F9" will start the code generation and if this was successful, start the compiled executable. AV will often not be you friend here! You may add resources by "#RESOURCE "&lt;resourcefilename&gt;.res", but even adding a version control block and a manifest does not ensure smooth testing.<br />
<br />
When there are syntax errors inside the BASIC code, these errors are shown in the IDE. In case of no error so far, the generated assembler code is passed to an assembler and linker, errors are shown in the IDE. Finally the created executable is run.<br />
<br />
For debuging you can inspect final or intermediate results with "MSGBOX", use "STR&#36;" or "HEX&#36;" for numeric results, or you can make use of "ODS" or "ODX", which show debug output in a special viewer, which doesn´t block code flow like a message box.<br />
<br />
<br />
Basically everything listed in features is allowed as syntax element. Expressions and block constructs have a maximum nesting level of 64.<br />
<br />
The generated assembler code still has potential for optimizing, but (as already mentioned) first i want to get it working and then i want to make it smaller, faster, whatever...<br />
<br />
The IDE will create a bunch of extra files mostly for debugging purposes, these will not be visible anymore in a final state.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please don´t post in this thread, use the "Discussions" thread.</span> More explanations will follow as needed.]]></description>
			<content:encoded><![CDATA[My IDE makes extensive use of hot keys, type CTRL + H for a list of key combinations<br />
<br />
In the IDE´s folder there is a file (list of available features.txt) listing all currently supported statements. Most statements are compatible to PB syntax<br />
<br />
I´m not absolutely sure, if my implementation of macros works correct under all circumstances, the same applies to math functions and all kinds of expressions, especially with new data types like QWORD and SBYTE. I am sure there will be bugs, issues and problems i didn´t find yet!<br />
<br />
<br />
Compiling the same code for 32 and 64 bit requires a special data type, which represents 32 bit in 32 bit and 64 bit in 64 bit: XWORD (unsigned) and XLONG (signed). Therefore all include files (i used José´s) must be prepared for this. Currently not all but about 2/3 have been translated and can be found in \Basic\Include_new.<br />
<br />
64 bit code is much more picky about alignment, 64 bit code refuses to work, if structure alignment is not correct. This produces hard to find errors, and i´m not sure if all structures have been translated properly for 64 bit.<br />
<br />
Inline assembler works as usual, i build ebp/rbp based stackframes and you can use PUSH and POP as usual, but in 64 bit code the stack pointer (rsp) must be 16 byte aligned before calls, otherwise you will experience all kinds of crashes. You may replace e/r by x for registers in order to write code, which compiles in 32 and 64 bit. Internally xax becomes eax in 32 bit and rax in 64 bit, this applies to all standard 32 bit registers (eax, ebx, ecx, edx, esi, edi, ebp, esp), obviously you cannot use r8 - r15 in 32 bit code.<br />
<br />
<br />
In 32 bit code the constant %x32_code and in 64 bit code %x64_code are predefined, so you can build conditional compiling blocks like:<br />
<br />
#ifdef %x64_code<br />
<br />
... 64 bit code goes here (must be compilable)<br />
<br />
#else<br />
<br />
... 32 bit code goes here (must be compilable)<br />
<br />
#endif<br />
<br />
<br />
While PowerBASIC allows for (variable)names like "cx" or "si", which are valid register names, my implementation currently doesn´t. So you must use different names. ATM there are some more words (in addition to language keywords), which are forbidden. You will get an error message in such cases.<br />
<br />
<br />
My object and COM implementation may need improvement, the focus was on being able to use COM services, which seems to work.Writing COM servers is possible but with some restrictions. Inheritance and multiple interfaces are not handled absolutely correct, i fear. There is nothing like #TLIB and "ME." (an object calling itself) doesn´t work yet.<br />
I want better error reporting, in many places you will get a simple "syntax error". It is possible to have more specific messages and i plan to do that, but it is not on top of my priority list.<br />
<br />
<br />
There are many ways of improving and optimizing my code, but for the moment the most important thing is making the "core" things stable.<br />
<br />
Then will be the time to add more features, currently it supports, what i would call the "core" features of a BASIC language. Feel free to ask for "core" features i might have missed. But i won´t add more or less "special" things, before the core can be considered actually stable. At the current point of development i must thoroughly test, what i have in order to avoid changes in the core functionality later on. Code generation must cover different scenarios, the currently supported feature set covers all these scenarios in (hopefully) all it´s aspects. So it should be suited for testing and finding bugs i missed. Further development will then be a variation or implementation of the existing core of code.<br />
<br />
E.g when passing arguments, such an argument can be: a literal, a constant, a variable, an array (as a whole, or as one single element), a structure (as a whole, or as one member of it), nested structures, a pointer, a resolved pointer, procedure returns, intrinsic functions (results from key words) and combinations and expressions of all of this. An argument can be passed "byref", "byval" and "bycopy". So there is a variety of possibilities, which must be taken care of.<br />
<br />
The most simple code for own tests would be:<br />
<br />
Code Select<br />
Code:<br />
#COMPILER JKB 32<br />
#COMPILE EXE<br />
<br />
FUNCTION MAIN<br />
<br />
...<br />
<br />
END FUNCTION<br />
<br />
<br />
Now you can fill in the body of MAIN (for convenience PBMAIN is also possible) with declarations of variables and code using the syntax known form PB. You can add subs and functions as usual. You may add "#INCLUDE "Win32Api.inc" for access to predefined constants and the Windows API.<br />
<br />
About 2/3 of José´s include files are already adapted to work in 64 bit Windows. There might still be issues though<br />
<br />
<br />
"F9" will start the code generation and if this was successful, start the compiled executable. AV will often not be you friend here! You may add resources by "#RESOURCE "&lt;resourcefilename&gt;.res", but even adding a version control block and a manifest does not ensure smooth testing.<br />
<br />
When there are syntax errors inside the BASIC code, these errors are shown in the IDE. In case of no error so far, the generated assembler code is passed to an assembler and linker, errors are shown in the IDE. Finally the created executable is run.<br />
<br />
For debuging you can inspect final or intermediate results with "MSGBOX", use "STR&#36;" or "HEX&#36;" for numeric results, or you can make use of "ODS" or "ODX", which show debug output in a special viewer, which doesn´t block code flow like a message box.<br />
<br />
<br />
Basically everything listed in features is allowed as syntax element. Expressions and block constructs have a maximum nesting level of 64.<br />
<br />
The generated assembler code still has potential for optimizing, but (as already mentioned) first i want to get it working and then i want to make it smaller, faster, whatever...<br />
<br />
The IDE will create a bunch of extra files mostly for debugging purposes, these will not be visible anymore in a final state.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please don´t post in this thread, use the "Discussions" thread.</span> More explanations will follow as needed.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Download and setup]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=120</link>
			<pubDate>Sun, 12 Apr 2026 11:51:23 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=71">Juergen Kuehlwein</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=120</guid>
			<description><![CDATA[Hi all,<br />
<br />
Below are a link and instructions for a setup - have fun<br />
<br />
<br />
whole package:  <a href="https://www.dropbox.com/scl/fi/tc6syg81rcd42u9spefdf/jkb.zip?rlkey=sfsfvic3tm0nim75unuj1ux5y&amp;st=cg1pbwwe&amp;dl=1" target="_blank" rel="noopener" class="mycode_url">https://www.dropbox.com/scl/fi/tc6syg81r...pbwwe&amp;dl=1</a><br />
update package:  <a href="https://www.dropbox.com/scl/fi/cl6294npcsohnv5b25mta/update.zip?rlkey=qyrhwn17e5jlrm5o16fsztuma&amp;st=8iebwzsq&amp;dl=1" target="_blank" rel="noopener" class="mycode_url">https://www.dropbox.com/scl/fi/cl6294npc...bwzsq&amp;dl=1</a><br />
<br />
<br />
<br />
The .zip file is about 40 MB and contains an updated version of my IDE and the complete tool chain necessary for the new "compiler". In fact working together with my IDE this is a complete compiler toolchain creating Windows executables (internally it is a code converter creating assembler code, which in turn is assembled to standard COFF .obj files and then linked to an execuatable). There is a linker (PoLink64.exe) included. A better choice would be Mircosoft´s linker (link.exe + a bunch of dlls), but this linker is not redistributable. It is included in a (free) community version of Visual C. You may download and install VC to have it installed on your machine. For using it you must specify this executable in Path Options Dialog in my IDE. A typical location for VC22 would be: C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx86\x86\link.exe. <br />
<br />
There might be problems with AV scanners, even Windows Defender sees some versions of JK-Basic.exe (the "compiler") as a potential threat, while virustotal sees no problem. In Windows 11 .exe files might not run, because there is no digital signature. The IDE itself (jk-ide.exe) and the "compiler" (jk-basic.exe) are not digitally signed, and newly created executables will have no digital signature, except you can digitally sign them yourself (the IDE can do that, if you have a certificate).<br />
<br />
As usual you can expand the package to a directory of your choice, it is path independent. I recommend a new location, if you already use my IDE. This version is still experimental, so in order not to destroy your work with an existing install, don´t just unpack this over it. Please don´t select a path way down in your folder tree, because there still is a limit in length for paths, which could come into play, if your install path is too long.<br />
<br />
<br />
When expanding Windows defender (or other AV) might block or quarantine some of the files, so be sure you got them all. In Windows 10 and below it is sufficient to add the "root" directory of this package to the AV´s exception list. I recommend doing this, because to my experience every now and then AV will "butt in" and produce all kinds of strange errors. Sometimes it can be really hard to get such false positives out of quaratine and get it to work again. The package doesn´t contain any dangerous or malicious things. Fell free to re-check with virustotal.<br />
<br />
Currently the tool chain only works with my IDE (jk-ide.exe), so you must be or make yourself familiar with it. There is a quite comprehensive help file (menu -&gt; help\JK-IDE Help)<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">For a start i would like you to do the following things:</span><br />
<br />
- download (full package, the "update package" is for updates, which requires only a subset of files to be replaced)<br />
<br />
- unzip<br />
<br />
- run jk-ide.exe (you maybe will be asked to specify a path for the PB compiler and for an include file set, please fill in the necessary paths and press "Apply". This happens only, if the IDE cannot find these paths itself)<br />
<br />
- the IDE will do some internal setup work, don´t worry, this is expected. It will tell you, when it is finished.<br />
<br />
- open "File" menu, select "New As" and "JKB", name and save this source file wherever you want, press "F9". Congratulations, you should have compiled your first 64 bit executable with JKB <br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please tell me, if this doesn´t work as described in "Discussions" thread. Don´t post in this thread!</span>]]></description>
			<content:encoded><![CDATA[Hi all,<br />
<br />
Below are a link and instructions for a setup - have fun<br />
<br />
<br />
whole package:  <a href="https://www.dropbox.com/scl/fi/tc6syg81rcd42u9spefdf/jkb.zip?rlkey=sfsfvic3tm0nim75unuj1ux5y&amp;st=cg1pbwwe&amp;dl=1" target="_blank" rel="noopener" class="mycode_url">https://www.dropbox.com/scl/fi/tc6syg81r...pbwwe&amp;dl=1</a><br />
update package:  <a href="https://www.dropbox.com/scl/fi/cl6294npcsohnv5b25mta/update.zip?rlkey=qyrhwn17e5jlrm5o16fsztuma&amp;st=8iebwzsq&amp;dl=1" target="_blank" rel="noopener" class="mycode_url">https://www.dropbox.com/scl/fi/cl6294npc...bwzsq&amp;dl=1</a><br />
<br />
<br />
<br />
The .zip file is about 40 MB and contains an updated version of my IDE and the complete tool chain necessary for the new "compiler". In fact working together with my IDE this is a complete compiler toolchain creating Windows executables (internally it is a code converter creating assembler code, which in turn is assembled to standard COFF .obj files and then linked to an execuatable). There is a linker (PoLink64.exe) included. A better choice would be Mircosoft´s linker (link.exe + a bunch of dlls), but this linker is not redistributable. It is included in a (free) community version of Visual C. You may download and install VC to have it installed on your machine. For using it you must specify this executable in Path Options Dialog in my IDE. A typical location for VC22 would be: C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx86\x86\link.exe. <br />
<br />
There might be problems with AV scanners, even Windows Defender sees some versions of JK-Basic.exe (the "compiler") as a potential threat, while virustotal sees no problem. In Windows 11 .exe files might not run, because there is no digital signature. The IDE itself (jk-ide.exe) and the "compiler" (jk-basic.exe) are not digitally signed, and newly created executables will have no digital signature, except you can digitally sign them yourself (the IDE can do that, if you have a certificate).<br />
<br />
As usual you can expand the package to a directory of your choice, it is path independent. I recommend a new location, if you already use my IDE. This version is still experimental, so in order not to destroy your work with an existing install, don´t just unpack this over it. Please don´t select a path way down in your folder tree, because there still is a limit in length for paths, which could come into play, if your install path is too long.<br />
<br />
<br />
When expanding Windows defender (or other AV) might block or quarantine some of the files, so be sure you got them all. In Windows 10 and below it is sufficient to add the "root" directory of this package to the AV´s exception list. I recommend doing this, because to my experience every now and then AV will "butt in" and produce all kinds of strange errors. Sometimes it can be really hard to get such false positives out of quaratine and get it to work again. The package doesn´t contain any dangerous or malicious things. Fell free to re-check with virustotal.<br />
<br />
Currently the tool chain only works with my IDE (jk-ide.exe), so you must be or make yourself familiar with it. There is a quite comprehensive help file (menu -&gt; help\JK-IDE Help)<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">For a start i would like you to do the following things:</span><br />
<br />
- download (full package, the "update package" is for updates, which requires only a subset of files to be replaced)<br />
<br />
- unzip<br />
<br />
- run jk-ide.exe (you maybe will be asked to specify a path for the PB compiler and for an include file set, please fill in the necessary paths and press "Apply". This happens only, if the IDE cannot find these paths itself)<br />
<br />
- the IDE will do some internal setup work, don´t worry, this is expected. It will tell you, when it is finished.<br />
<br />
- open "File" menu, select "New As" and "JKB", name and save this source file wherever you want, press "F9". Congratulations, you should have compiled your first 64 bit executable with JKB <br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Please tell me, if this doesn´t work as described in "Discussions" thread. Don´t post in this thread!</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[A new sub-forum for Juergen Kuehlwein's JKB (32/64 bit Compiler)]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=119</link>
			<pubDate>Sun, 12 Apr 2026 05:36:45 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=1">Albert Richheimer</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=119</guid>
			<description><![CDATA[Welcome to the new sub-forum for Juergen Kuehlwein's JKB. Juergen is going public with his new JKB (32/64 bit Compiler). Please follow the usual PUMP rules for posting in this area.<br />
<br />
Cheers,<br />
Albert (PUMP admin)]]></description>
			<content:encoded><![CDATA[Welcome to the new sub-forum for Juergen Kuehlwein's JKB. Juergen is going public with his new JKB (32/64 bit Compiler). Please follow the usual PUMP rules for posting in this area.<br />
<br />
Cheers,<br />
Albert (PUMP admin)]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How many "1" bits /Is Number a Power of 2]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=117</link>
			<pubDate>Mon, 16 Mar 2026 09:54:49 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=23">Dale Yarker</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=117</guid>
			<description><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>'The FASTPROCs here are for both PBWin 10 and PBCC 6.<br />
'For older PB versions change FASTPROC to FUNCTION.<br />
'The demo (in PBMAIN below) would need significant change to compile in older<br />
'versions of PB.<br />
#compile exe<br />
#dim all<br />
#if %def(%pb_cc32) 'ignore this in PBWin<br />
  #console off     'no unneeded in PBCC<br />
#endif<br />
'<br />
'#### Please start thread in Programming for comments/questions. ####<br />
'<br />
'I want a solitare game that was not in old PB formum Source Code.<br />
'Do it myself.<br />
'That requires shuffling cards. Instead of repeating shuffle code for other<br />
'games make a DLL.<br />
'Shuffling requires PRNG(s), and seeds for PRNDs. They are useful for more<br />
'than just card game, so another DLL.<br />
'One of the PRNG algorithms fails if seed is a power of 2.<br />
'<br />
'(PRNG is pseudo Random Number Generator, NUT is Number Under Test.)<br />
'<br />
'How many bits are "1"?<br />
''Simple use of the assembly POPCNT needed in power of 2 procs.<br />
''is DWORD/LONG agnostic<br />
fastproc BitCount(byval NUT as long) as long<br />
  ! popcnt eax, NUT<br />
  ! mov NUT, eax<br />
end fastproc = NUT<br />
'<br />
'Is a DWORD number a power of 2?<br />
fastproc IsPowerOf2Dw (byval NUT as long) as long<br />
  ! mov ebx, NUT        'so not to modify NUT<br />
  ! and ebx, &amp;h00000001 'without this 1 returns as PO2<br />
  !  jz IsEven<br />
  ! jmp NotPO2<br />
  IsEven:<br />
  ! popcnt ebx, NUT<br />
  ! cmp ebx, 1<br />
  ! jne NotPO2<br />
  ! mov NUT, -1<br />
  ! jmp Done<br />
  NotPO2:          '   -4 -8<br />
  ! mov NUT, 0<br />
  Done:<br />
end fastproc = NUT<br />
'<br />
'Is a LONG number a power of 2?<br />
''(Second procedure because in DWORD bit 31 is MSB of the number, while<br />
'''in a LONG it is the sign flag and remaining bits are in 2s compliment<br />
'''format.)<br />
fastproc IsPowerOf2Lg (byval NUT as long) as long<br />
  'check if NUT is negative<br />
  !  bt NUT, 31<br />
  ! jc NotPO2<br />
  ! mov ebx, NUT<br />
  ! and ebx, &amp;00000001<br />
  !  jz IsEven<br />
  ! jmp NotPO2<br />
  IsEven:<br />
  ! popcnt ebx, NUT<br />
  ! cmp ebx, 1<br />
  ! jne NotPO2<br />
  ! mov NUT, -1<br />
  ! jmp Done<br />
  NotPO2:<br />
  ! mov NUT, 0<br />
  Done:<br />
end fastproc = NUT<br />
'<br />
'###############################################################################<br />
function pbmain () as long<br />
  local hTWin, NumD as dword<br />
  local NumL, Retrn as long<br />
  txt.window("BitCount, IsPowerOf2Dw and IsPowerOf2Lg"&#36;&#36;, 75, 50, 27, 40) _<br />
                                                                        to hTWin<br />
  '<br />
  txt.color = %rgb_blue : txt.print "BitCount" : txt.color = %rgb_black<br />
  NumL = 1 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = 2 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = 15 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = &amp;h80050006 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  '<br />
  txt.print : txt.color = %rgb_blue<br />
  txt.print "Is DWORD a power of 2?"&#36;&#36; : txt.color = %rgb_black<br />
  NumD = 1 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 4 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 5 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 4294967294 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  '<br />
  txt.print  : txt.color = %rgb_blue<br />
  txt.print "Is LONG a power of 2?"&#36;&#36; : txt.color = %rgb_black<br />
  NumL = 1 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -1 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 8 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -8 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 128 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -128 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 1024 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -1024 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 1026 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -11026 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  '<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print "Any key to close."&#36;&#36;<br />
  txt.waitkey&#36;<br />
  exit function<br />
  PrintCount:<br />
    txt.print dec&#36;(NumL) + " has " + dec&#36;(Retrn) + " ""1"" bits."<br />
  return<br />
  PrintDwd:<br />
    txt.print dec&#36;(NumD);<br />
    if Retrn then<br />
      txt.print " is"&#36;&#36;<br />
    else<br />
      txt.print " is not"&#36;&#36;<br />
    end if<br />
  return<br />
  PrintLng:<br />
    txt.print dec&#36;(NumL);<br />
    if Retrn then<br />
      txt.print " is"&#36;&#36;<br />
    else<br />
      txt.print " is not"&#36;&#36;<br />
    end if<br />
  return<br />
end function<br />
'#### Please start thread in Programming for comments/questions. ####</code></div></div>]]></description>
			<content:encoded><![CDATA[<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>'The FASTPROCs here are for both PBWin 10 and PBCC 6.<br />
'For older PB versions change FASTPROC to FUNCTION.<br />
'The demo (in PBMAIN below) would need significant change to compile in older<br />
'versions of PB.<br />
#compile exe<br />
#dim all<br />
#if %def(%pb_cc32) 'ignore this in PBWin<br />
  #console off     'no unneeded in PBCC<br />
#endif<br />
'<br />
'#### Please start thread in Programming for comments/questions. ####<br />
'<br />
'I want a solitare game that was not in old PB formum Source Code.<br />
'Do it myself.<br />
'That requires shuffling cards. Instead of repeating shuffle code for other<br />
'games make a DLL.<br />
'Shuffling requires PRNG(s), and seeds for PRNDs. They are useful for more<br />
'than just card game, so another DLL.<br />
'One of the PRNG algorithms fails if seed is a power of 2.<br />
'<br />
'(PRNG is pseudo Random Number Generator, NUT is Number Under Test.)<br />
'<br />
'How many bits are "1"?<br />
''Simple use of the assembly POPCNT needed in power of 2 procs.<br />
''is DWORD/LONG agnostic<br />
fastproc BitCount(byval NUT as long) as long<br />
  ! popcnt eax, NUT<br />
  ! mov NUT, eax<br />
end fastproc = NUT<br />
'<br />
'Is a DWORD number a power of 2?<br />
fastproc IsPowerOf2Dw (byval NUT as long) as long<br />
  ! mov ebx, NUT        'so not to modify NUT<br />
  ! and ebx, &amp;h00000001 'without this 1 returns as PO2<br />
  !  jz IsEven<br />
  ! jmp NotPO2<br />
  IsEven:<br />
  ! popcnt ebx, NUT<br />
  ! cmp ebx, 1<br />
  ! jne NotPO2<br />
  ! mov NUT, -1<br />
  ! jmp Done<br />
  NotPO2:          '   -4 -8<br />
  ! mov NUT, 0<br />
  Done:<br />
end fastproc = NUT<br />
'<br />
'Is a LONG number a power of 2?<br />
''(Second procedure because in DWORD bit 31 is MSB of the number, while<br />
'''in a LONG it is the sign flag and remaining bits are in 2s compliment<br />
'''format.)<br />
fastproc IsPowerOf2Lg (byval NUT as long) as long<br />
  'check if NUT is negative<br />
  !  bt NUT, 31<br />
  ! jc NotPO2<br />
  ! mov ebx, NUT<br />
  ! and ebx, &amp;00000001<br />
  !  jz IsEven<br />
  ! jmp NotPO2<br />
  IsEven:<br />
  ! popcnt ebx, NUT<br />
  ! cmp ebx, 1<br />
  ! jne NotPO2<br />
  ! mov NUT, -1<br />
  ! jmp Done<br />
  NotPO2:<br />
  ! mov NUT, 0<br />
  Done:<br />
end fastproc = NUT<br />
'<br />
'###############################################################################<br />
function pbmain () as long<br />
  local hTWin, NumD as dword<br />
  local NumL, Retrn as long<br />
  txt.window("BitCount, IsPowerOf2Dw and IsPowerOf2Lg"&#36;&#36;, 75, 50, 27, 40) _<br />
                                                                        to hTWin<br />
  '<br />
  txt.color = %rgb_blue : txt.print "BitCount" : txt.color = %rgb_black<br />
  NumL = 1 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = 2 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = 15 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  NumL = &amp;h80050006 : Retrn = BitCount(NumL) : gosub PrintCount<br />
  '<br />
  txt.print : txt.color = %rgb_blue<br />
  txt.print "Is DWORD a power of 2?"&#36;&#36; : txt.color = %rgb_black<br />
  NumD = 1 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 4 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 5 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  NumD = 4294967294 : Retrn = IsPowerOf2Dw(NumD) : gosub PrintDwd<br />
  '<br />
  txt.print  : txt.color = %rgb_blue<br />
  txt.print "Is LONG a power of 2?"&#36;&#36; : txt.color = %rgb_black<br />
  NumL = 1 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -1 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 8 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -8 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 128 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -128 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 1024 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -1024 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = 1026 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  NumL = -11026 : Retrn = IsPowerOf2Lg(NumL) : gosub PrintLng<br />
  '<br />
  txt.print<br />
  txt.color = %rgb_green<br />
  txt.print "Any key to close."&#36;&#36;<br />
  txt.waitkey&#36;<br />
  exit function<br />
  PrintCount:<br />
    txt.print dec&#36;(NumL) + " has " + dec&#36;(Retrn) + " ""1"" bits."<br />
  return<br />
  PrintDwd:<br />
    txt.print dec&#36;(NumD);<br />
    if Retrn then<br />
      txt.print " is"&#36;&#36;<br />
    else<br />
      txt.print " is not"&#36;&#36;<br />
    end if<br />
  return<br />
  PrintLng:<br />
    txt.print dec&#36;(NumL);<br />
    if Retrn then<br />
      txt.print " is"&#36;&#36;<br />
    else<br />
      txt.print " is not"&#36;&#36;<br />
    end if<br />
  return<br />
end function<br />
'#### Please start thread in Programming for comments/questions. ####</code></div></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Notepad++ hacked]]></title>
			<link>http://pump.richheimer.de/showthread.php?tid=116</link>
			<pubDate>Tue, 03 Feb 2026 01:36:33 +0000</pubDate>
			<dc:creator><![CDATA[<a href="http://pump.richheimer.de/member.php?action=profile&uid=164">Stanley Durham</a>]]></dc:creator>
			<guid isPermaLink="false">http://pump.richheimer.de/showthread.php?tid=116</guid>
			<description><![CDATA[Chinese Hackers Remote Executed Code Via Notepad++ for 6 Months<br />
_______________________________________________________<br />
<br />
Please do not post any Youtube links (and others) without comment.<br />
<br />
Thank you<br />
Albert (PUMP admin)]]></description>
			<content:encoded><![CDATA[Chinese Hackers Remote Executed Code Via Notepad++ for 6 Months<br />
_______________________________________________________<br />
<br />
Please do not post any Youtube links (and others) without comment.<br />
<br />
Thank you<br />
Albert (PUMP admin)]]></content:encoded>
		</item>
	</channel>
</rss>