Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

PBDLL, ini file and ballon tooltips sample

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBDLL, ini file and ballon tooltips sample

    Code:
    ' PBini sample, showing how to save and retrieve settings from an ini
    ' file. Program stores and sets location, checkbox values and file
    ' lists in comboboxes. Wrapper functions for ini save/read included.
    ' Also threw in code for balloon tooltips, since I have got several
    ' questions about it the last couple of days. Is silly and may not
    ' work in older systems, but it's always fun to try new things..   [img]http://www.powerbasic.com/support/forums/smile.gif[/img]
    '
    ' The registry? MS now recommends us NOT to use the registry for
    ' private settings. Good old ini files are easy to maintain and
    ' settings are not lost if user decides to restore the registry
    ' with older copy. Many times, old ways still works best..
    '
    ' Public Domain for PB/DLL 6.0-6.1 by Borje Hagsten, January 2002.
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Declares
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    '------------------------------------------
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMDLG32.INC"
    '------------------------------------------
    GLOBAL hToolTips AS LONG, iniFile AS STRING
    '------------------------------------------
    %TTS_ALWAYSTIP     = &H01
    %TTS_BALLOON       = &H40
    %TTF_IDISHWND      = &H0001
    %TTF_SUBCLASS      = &H0010
    %TTM_ADDTOOL       = %WM_USER +  4
    %TTM_DELTOOL       = %WM_USER +  5
    %TTM_GETTOOLINFO   = %WM_USER +  8
    '------------------------------------------
    DECLARE SUB InitCommonControls LIB "COMCTL32.DLL" ALIAS "InitCommonControls" ()
    '------------------------------------------
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
    DECLARE FUNCTION GetAppPath AS STRING
    DECLARE FUNCTION IniGetString(BYVAL sSection AS STRING, BYVAL sKey AS STRING, _
                                  BYVAL sDefault AS STRING, BYVAL sFile AS STRING) AS STRING
    DECLARE FUNCTION IniSetString(BYVAL sSection AS STRING, BYVAL sKey AS STRING, _
                                  BYVAL sStr AS STRING, BYVAL sFile AS STRING) AS LONG
    DECLARE FUNCTION ToolTip_Create (BYVAL hWnd AS LONG) AS LONG
    DECLARE FUNCTION ToolTip_SetToolTip (BYVAL hWnd AS LONG, BYVAL txt AS STRING) AS LONG
    DECLARE SUB      IniReadToCombo(BYVAL hCB AS LONG, BYVAL sSection AS STRING, _
                                    BYVAL sKey AS STRING, BYVAL sFile AS STRING)
    DECLARE SUB      IniSaveCombo(BYVAL hCB AS LONG, BYVAL sSection AS STRING, _
                                  BYVAL sKey AS STRING, BYVAL sFile AS STRING)
    DECLARE SUB      UpdateComboList (BYVAL hCB AS LONG, BYVAL strTxt AS STRING)
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main entrance - build main dialog and controls, etc
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION PBMAIN () AS LONG
      LOCAL hDlg AS LONG
      iniFile = GetAppPath + "MyProg.ini"
     
      DIALOG NEW 0, "Ini file sample",,, 240, 94, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
     
      CONTROL ADD LABEL,   hDlg, 10, "File 1:", 6, 6, 24, 12
      CONTROL ADD COMBOBOX, hDlg, 50, ,      30,  4, 184, 80, %WS_CHILD OR _
                  %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN OR %CBS_AUTOHSCROLL
      CONTROL ADD BUTTON,  hDlg, 20, "...", 216,  5,  18, 12
      CONTROL SEND hDlg, 20, %WM_SETFONT, GetStockObject(%SYSTEM_FONT), 0 'for better dots..
     
      CONTROL ADD LABEL,   hDlg, 11, "File 2:", 6, 22, 24, 12
      CONTROL ADD COMBOBOX, hDlg, 51, ,      30, 20, 184,  80, %WS_CHILD OR _
                  %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN OR %CBS_AUTOHSCROLL
      CONTROL ADD BUTTON,  hDlg, 21, "...", 216, 21,  18,  12
      CONTROL SEND hDlg, 21, %WM_SETFONT, GetStockObject(%SYSTEM_FONT), 0
     
      CONTROL ADD FRAME,     hDlg, 90, "Settings ",          6, 38,  228,  28
      CONTROL ADD CHECKBOX,  hDlg, 70, "Beep at startup ",  12, 49,   70,  14
      CONTROL ADD CHECKBOX,  hDlg, 71, "Beep at exit ",    150, 49,   70,  14
      CONTROL ADD BUTTON,    hDlg, %IDCANCEL, "&Ok",       184, 74,   50,  14
     
      ' Tip: can use GetWindow(hCombo, %GW_CHILD) to get combobox edit
      ' field's handle, if you want to set tooltips for that part too..
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 50), " List of my files ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 51), " List of your files ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 20), " Select my files ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 21), " Select your files ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, %IDCANCEL), " Store settings and close dialog ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 70), " Beep when program starts ")
      CALL ToolTip_SetToolTip (GetDlgItem(hDlg, 71), " Beep when program ends ")
     
      DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main dialog's callback procedure
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc() AS LONG
      SELECT CASE CBMSG
         CASE %WM_INITDIALOG '<- entry point, invoked once by DIALOG SHOW..
            LOCAL lRes AS LONG, x AS LONG, y AS LONG, Style AS DWORD
            LOCAL f AS STRING, Buffer AS STRING, Path AS STRING
     
            'Retrive settings from ini file. Compare with impossible def value for xPos
            'to see if any values has been stored (it is first time prog is run or not).
            x = VAL(IniGetString("Program", "xPos", "-32000", iniFile)) 'read last x pos
            y = VAL(IniGetString("Program", "yPos", "0", iniFile))      'read last y pos
            IF x > -32000 THEN DIALOG SET LOC CBHNDL, x, y              'if last pos, set location
     
            IniReadToCombo GetDlgItem(CBHNDL, 50), "MyFiles", "File", iniFile 'get last file list
            IniReadToCombo GetDlgItem(CBHNDL, 51), "YourFiles", "File", iniFile
            lRes = VAL(IniGetString("MyFiles", "LastSel", "", iniFile))
            IF lRes <> %CB_ERR THEN CONTROL SEND CBHNDL, 50, %CB_SETCURSEL, lRes, 0
            lRes = VAL(IniGetString("YourFiles", "LastSel", "", iniFile))
            IF lRes <> %CB_ERR THEN CONTROL SEND CBHNDL, 51, %CB_SETCURSEL, lRes, 0
     
            lRes = VAL(IniGetString("Program", "ExitBeep", "0", iniFile))
            CONTROL SET CHECK CBHNDL, 71, lRes
            lRes = VAL(IniGetString("Program", "EnterBeep", "0", iniFile))
            CONTROL SET CHECK CBHNDL, 70, lRes
            IF lRes THEN BEEP
            DIALOG DOEVENTS '<- always good to do right before dialog becomes visible
     
         CASE %WM_DESTROY 'store all settings at exit
            DIALOG GET LOC CBHNDL TO x, y
            IniSetString "Program", "xPos", FORMAT$(x), iniFile
            IniSetString "Program", "yPos", FORMAT$(y), iniFile
            IniSaveCombo GetDlgItem(CBHNDL, 50), "MyFiles", "File", iniFile
            IniSaveCombo GetDlgItem(CBHNDL, 51), "YourFiles", "File", iniFile
            CONTROL GET CHECK CBHNDL, 70 TO lRes
            IniSetString "Program", "EnterBeep", FORMAT$(lRes), iniFile
            CONTROL GET CHECK CBHNDL, 71 TO lRes
            IniSetString "Program", "ExitBeep", FORMAT$(lRes), iniFile
            IF lRes THEN BEEP
     
         CASE %WM_COMMAND         '<- this is where response to controls can be made
             IF CBCTLMSG = %BN_CLICKED THEN '<- this the message sent
               SELECT CASE CBCTL            '<- from what control id?
                  CASE 20, 21               '<- ... -buttons
                     Path   = CURDIR$
                     f      = "*.TXT"
                     Buffer = "Text Files (*.TXT)|*.TXT|"
                     Buffer = Buffer & "All Files (*.*)|*.*"
                     Style  = %OFN_ENABLEHOOK OR %OFN_EXPLORER OR %OFN_FILEMUSTEXIST
                     IF OpenFileDialog(CBHNDL, "", f, Path, Buffer, "TXT" , Style) THEN
                        IF CBCTL = 20 THEN
                           UpdateComboList GetDlgItem(CBHNDL, 50), f
                        ELSE
                           UpdateComboList GetDlgItem(CBHNDL, 51), f
                        END IF
                     END IF
     
                  CASE %IDCANCEL  '<- Ok pressed - exit dialog
                     DIALOG END CBHNDL
               END SELECT
            END IF
     
      END SELECT
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Get string from ini file - wrapper for GetPrivateProfileString
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION IniGetString(BYVAL sSection AS STRING, BYVAL sKey AS STRING, _
                          BYVAL sDefault AS STRING, BYVAL sFile AS STRING) AS STRING
      LOCAL RetVal AS LONG, zResult AS ASCIIZ * 2000, _
            zSection AS ASCIIZ * %MAX_PATH, zKey AS ASCIIZ * %MAX_PATH, _
            zDefault AS ASCIIZ * %MAX_PATH, zFile AS ASCIIZ * %MAX_PATH
     
      zSection = sSection : zKey  = sKey
      zDefault = sDefault : zFile = sFile
     
      RetVal = GetPrivateProfileString(zSection, zKey, zDefault, zResult, SIZEOF(zResult), zFile)
      IF RetVal THEN FUNCTION = LEFT$(zResult, RetVal)
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Set string to ini file - wrapper for WritePrivateProfileString
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION IniSetString(BYVAL sSection AS STRING, BYVAL sKey AS STRING, _
                          BYVAL sStr AS STRING, BYVAL sFile AS STRING) AS LONG
      LOCAL zSection AS ASCIIZ * %MAX_PATH, zKey AS ASCIIZ * %MAX_PATH, _
            zStr AS ASCIIZ * 2000, zFile AS ASCIIZ * %MAX_PATH
     
      zSection = sSection : zKey  = sKey : zStr = sStr : zFile = sFile
      FUNCTION = WritePrivateProfileString(zSection, zKey, zStr, zFile)
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Get combobox contents from ini file
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    SUB IniReadToCombo(BYVAL hCB AS LONG, BYVAL sSection AS STRING, _
                       BYVAL sKey AS STRING, BYVAL sFile AS STRING)
      LOCAL iCnt AS LONG, tmpStr AS STRING
     
      DO
         tmpStr = IniGetString(sSection, sKey & FORMAT$(iCnt + 1), "", sFile)
         IF LEN(tmpStr) = 0 THEN EXIT DO
         SendMessage hCB, %CB_ADDSTRING, 0, STRPTR(tmpStr)
         INCR iCnt
      LOOP
    END SUB
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Save combobox contents and current selected item number to ini file
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    SUB IniSaveCombo(BYVAL hCB AS LONG, BYVAL sSection AS STRING, _
                     BYVAL sKey AS STRING, BYVAL sFile AS STRING)
      LOCAL cb AS LONG, cbListCount AS LONG, cmpTxt AS STRING
     
      cbListCount = SendMessage(hCB, %CB_GETCOUNT, 0, 0) 'get cb's list count
      IF cbListCount > 0 THEN
         FOR cb = 0 TO cbListCount - 1                   'loop through existing items
            cmpTxt = SPACE$(SendMessage(hCB, %CB_GETLBTEXTLEN, cb, 0) + 1)
            CALL SendMessage(hCB, %CB_GETLBTEXT, cb, STRPTR(cmpTxt))      'get text
            cmpTxt = EXTRACT$(cmpTxt, CHR$(0))
            IniSetString sSection, sKey & FORMAT$(cb + 1), cmpTxt, sFile  'store text
         NEXT cb
      END IF
     
      cb = SendMessage(hCB, %CB_GETCURSEL, 0, 0) 'also store last selected file
      IniSetString sSection, "LastSel", FORMAT$(cb), sFile
     
    END SUB
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Get AppPath (returns complete path - including trailing backslash)
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION GetAppPath AS STRING
      LOCAL zPath AS ASCIIZ * %MAX_PATH
      GetModuleFileName GetModuleHandle(""), zPath, %MAX_PATH
      FUNCTION = LEFT$(zPath, INSTR(-1, zPath, "\"))
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Keep a combobox populated
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    SUB UpdateComboList (BYVAL hCB AS LONG, BYVAL strTxt AS STRING)
      IF LEN(strTxt) THEN
         LOCAL cb AS LONG, cbListCount AS LONG, cmpTxt AS STRING
         cbListCount = SendMessage(hCB, %CB_GETCOUNT, 0, 0)
     
         IF 0 < cbListCount THEN
             FOR cb = 0 TO cbListCount - 1
                 cmpTxt = SPACE$(SendMessage(hCB, %CB_GETLBTEXTLEN, cb, 0) + 1)
                 CALL SendMessage(hCB, %CB_GETLBTEXT, cb, STRPTR(cmpTxt))
                 cmpTxt = EXTRACT$(cmpTxt, CHR$(0))       'remove CHR$(0)
                 IF UCASE$(cmpTxt) = UCASE$(strTxt) THEN 'if already there - delete
                    strTxt = cmpTxt                     '(it will be added to top later..)
                    CALL SendMessage(hCB, %CB_DELETESTRING, cb, 0)
                    EXIT FOR
                 END IF
             NEXT cb
         END IF
                 'now, insert new items at the top of the list and select it
         CALL SendMessage(hCB, %CB_INSERTSTRING, 0, BYVAL STRPTR(strTxt))
         CALL SendMessage(hCB, %CB_SETCURSEL, 0, 0)
     
         IF cbListCount > 19 THEN 'if to only store max 20 items (0 to 19)
            CALL SendMessage(hCB, %CB_DELETESTRING, cbListCount, 0)
         END IF
      END IF
    END SUB
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Internal use only - create tooltips control if needed.
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION ToolTip_Create (BYVAL hWnd AS LONG) AS LONG
      IF hToolTips = 0 THEN
         IF hWnd = 0 THEN hWnd = GetActiveWindow()
         IF hWnd = 0 THEN EXIT FUNCTION
         CALL InitCommonControls
         hToolTips = CreateWindowEx(0, "tooltips_class32", "", %TTS_ALWAYSTIP OR %TTS_BALLOON, _
                 0, 0, 0, 0, hWnd, BYVAL 0&, GetModuleHandle(""), BYVAL %NULL)
      END IF
      FUNCTION = hToolTips
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Add a tooltip to a window/control - original code by E.B. Knoppert
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION ToolTip_SetToolTip (BYVAL hWnd AS LONG, BYVAL txt AS STRING) AS LONG
      LOCAL ti AS TOOLINFO
     
      IF ToolTip_Create(GetParent(hWnd)) = 0 THEN EXIT FUNCTION 'ensure creation
     
      ti.cbSize   = LEN(ti)
      ti.uFlags   = %TTF_SUBCLASS OR %TTF_IDISHWND
      ti.hWnd     = GetParent(hWnd)
      ti.uId      = hWnd
     
      'Remove existing tooltip
      IF SendMessage (hToolTips, %TTM_GETTOOLINFO, 0, BYVAL VARPTR(ti)) THEN
         SendMessage hToolTips, %TTM_DELTOOL, 0, BYVAL VARPTR(ti)
      END IF
     
      ti.cbSize   = LEN(ti)
      ti.uFlags   = %TTF_SUBCLASS OR %TTF_IDISHWND
      ti.hWnd     = GetParent(hWnd)
      ti.uId      = hWnd
      ti.lpszText = STRPTR(txt)
     
      FUNCTION = SendMessage(hToolTips, %TTM_ADDTOOL, 0, BYVAL VARPTR(ti)) 'add tooltip
    END FUNCTION

    ------------------


    [This message has been edited by Borje Hagsten (edited January 25, 2002).]
Working...
X