Announcement

Collapse
No announcement yet.

gbThreads

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

  • gbThreads

    I've found some time to work on a new release of gbThreads, something to resolve issues I've seen with the new forum.

    If you have anything on your wishlist, now is a good to speak up.

    The Poffs output format is not one I use, so I'm considering removing it to simplify the code, reduce the indexing time and reduce the index file sizes (about 1GB savings).

    If anyone has a serious objection, please speak up.

  • #2
    Hi Gary,

    That's fabulous news!

    I had installed two earlier versions, and IIRC, I got stuck when attempting to do periodic updates to the data.

    What's a reasonable update frequency? Once a week? Once a month?

    And will that "refresh to most current" function be easy to perform?

    I really appreciate your work on this, because I am constantly doing searches on the forums and trying to stay up-to-date, while of course, being able to research old and new discussions and code examples. While I had it running, I found gbThreads to be a very valuable tool!

    Thanks,
    -John


    Comment


    • #3
      Since the gbThreads program has become so robust, I've stopped using the POFFS software as well. I'll forever be in Börje's debt for such a tool being made and for PB allowing it to be hosted by him, for me a bit, and then others to replace it with better tools! As it stands now, I don't have any real feature requests, but I'd love it if the threads were stored in some type of archived file versus individual files. When you 7zip the gbThreads program, it shrinks phenomenally and I sometimes forget to do that when transferring from my home computer to a flash drive or my work computer...all those individual files take a lot of time to copy over!
      Donnie Ewald
      [email protected]

      Comment


      • #4
        Hey John!
        With the new forum, I'm still working to figure out how best to get new content to gbThreads users. I prefer to let users download their own threads and build their own indexes - on a schedule of their choosing. But the new forum is not as easy to work with as the old one.

        The fallback position is for me to create a new download monthly. I'll know more in a few days.


        And, howdy, Don!
        I've considered using an SQLite database, to hold the threads and local images. That should meet your request, yes? I don't know squat about SQLite but I'll take a look at it. I'd like to understand any possible hits on indexing and search speeds and how easily I can insert it into my current gbThreads code. I'll ask questions of the SQLite folks on the forums as I better understand the option.

        Another approach would be to simply put all the threads into a single, large file and all of the local images into another large file, with index files maintained to find the bytes of each file. But if I understand your request correctly, you'd like that combined threads file zipped and have content extracted/unzipped real time as needed? If so, that seems like a really big performance hit when searching for content across the entire thread library. I'll look into it.

        Comment


        • #5
          Hey old friend!

          I like the "Using larges file" idea very, very much. :-)

          Whatever your choice is... Thank you!

          Pierre

          Comment


          • #6
            Gary, I'm fine with either approach that you mention and I don't mind the storage space used as I've plenty of room to spare. It's mostly the thousands upon thousands of separate HTML files across several folders.
            Donnie Ewald
            [email protected]

            Comment


            • #7
              I very rarely use case-sensitive searches. Removing that feature would speed indexing and reduce file sizes.

              Does anyone have a strong need to do case-sensitive searches?

              Comment


              • #8
                Hi Gary, I never use it and would not miss it if it is removed.

                Comment


                • #9
                  Gary,

                  FWIW, I can't recall the last time I NEEDED a case-sensitive search in a general tool. In some of my own programs, I might sometimes occasionally use case-sensitive search, maybe.

                  More important to me is being able to choose how to match punctuation: abc-efg abc_efg abcedfg ... all treated the same? sometimes OK, mostly not.

                  -John

                  Comment


                  • #10
                    We've had a bit of a setback. Adam and I contacted vBulletin, looking for a way to automate downloading thread images. This is what we got ...

                    Sorry, there is no supported way to do this. Attachments aren't designed to be bulk downloaded in this way.
                    I had the impression that they have a programming staff whom we could pay $$ for generating code to download the images, but I'm not prepared to pursue that approach just yet.

                    It's the image URLs that use the "fetch" command that are the issue. The URLDownloadToFile API does not work with that type of URL. Also, an embedded browser of the type that Jose's has provided code for will not display "fetched" images either.

                    That pretty much just leaves the manual approach, which is to open each image in Chrome, which will display the fetched images, then manually right-click-save the image using a supplied filename. That works but there are some 3,000 image involved so some kind of animation is desired. I highly suspect that sequence can be animated but was hoping not to have to go that route. As soon as I get the rest of the new gbThreads working, I'll focus on getting the images.

                    I just did a quick check and it appears that only the threads created since we moved to the new forum use the fetch method, so that should help reduce the amount of manual effort to create the first full folder of thread images.

                    Comment


                    • #11
                      Originally posted by Gary Beene View Post
                      We've had a bit of a setback. Adam and I contacted vBulletin, looking for a way to automate downloading thread images. This is what we got ...

                      It's the image URLs that use the "fetch" command that are the issue. The URLDownloadToFile API does not work with that type of URL. Also, an embedded browser of the type that Jose's has provided code for will not display "fetched" images either.
                      On one of your other posts I posted code that will download the image as long as you identify yourself and supply the credential Cookies.
                      if you don't what to use your credentials or don't want users to supply their credentials, you can maybe ask Adam to create a user for this purpose.

                      https://forum.powerbasic.com/forum/u...184#post783184

                      if you are interested I actually made that code into a function similar to URLDownloadToFile

                      Comment


                      • #12
                        Links with fetch, require user to identify themselves to get them.
                        This is achieved via Cookies, that are supplied during the initial login to the vBulletin forum.

                        Here is the function that can fetch the image and save it. provided you supply a valid PBForum username and password.

                        the username and password are used only on the first request, all subsequent requests for images will used supplied cookies until program completes.

                        Code:
                        ' ========================================================================================
                        ' The following example shows how to open an HTTP connection, send an HTTP request, and
                        ' read the response as an IStream. The data from the IStream is written to a file.
                        ' ========================================================================================
                        
                        #COMPILE EXE
                        #DIM ALL
                        #INCLUDE "httprequest.inc"
                        #INCLUDE "ole2utils.inc"
                        #INCLUDE "WinInet.inc"
                        
                        ' ========================================================================================
                        ' Main
                        ' ========================================================================================
                        FUNCTION PBMAIN
                        LOCAL username, password AS STRING
                        LOCAL OnlineImageURL, LocalImageURL AS STRING
                        
                        username = "User Name"                 ' PUT YOUR FORUM LOGIN USERNAME
                        password = "myPassword"                 ' AND PASSWORD
                        
                        
                           OnlineImageURL = "https://forum.powerbasic.com/filedata/fetch?id=781720&d=1559518390"
                           LocalImageURL = EXE.PATH$ + "rodimage.jpg"
                        
                        IF DownloadUrlPBForum ("https://forum.powerbasic.com/filedata/fetch?id=783212&d=1564353461", LocalImageURL, username, password) = %false THEN MSGBOX "Failed"
                        IF DownloadUrlPBForum (OnlineImageURL,"", username, password)= %false THEN MSGBOX "Failed"
                        
                        END FUNCTION
                        
                        
                        FUNCTION DownloadUrlPBForum(OnlineImageURL AS STRING, LocalImageURL AS STRING,Username AS STRING, Password AS STRING) AS LONG
                         LOCAL pWHttp AS IWinHttpRequest
                         LOCAL vBody, vSTream AS VARIANT
                         LOCAL pIStream AS IStream
                         LOCAL Buffer AS STRING * 8192
                         LOCAL strBuffer, vb_login_md5password, vb_login_md5password_utf AS STRING
                         LOCAL cbRead AS DWORD
                         LOCAL iSucceeded AS INTEGER
                         LOCAL  wsHeaders, wTemp1, wFilename AS WSTRING
                         LOCAL Cookies () AS WSTRING
                         LOCAL CookiesCnt, lCount1, lCount2 AS LONG
                         STATIC wsCookies, vb_UserID, vb_PassHash AS WSTRING
                        
                         FUNCTION = %false
                        
                           ' Creates an instance of the HTTP service
                           pWHttp = NEWCOM "WinHttp.WinHttpRequest.5.1"
                           IF ISNOTHING(pWHttp) THEN EXIT FUNCTION
                        
                         TRY
                         IF  vb_UserID ="" OR vb_PassHash ="" THEN     'phase1 first time we call function, after we dont need
                            REPLACE $SPC WITH "+" IN username        ' No Spaces in Username
                            vb_login_md5password     = GetMD5HASH(password)                   'Prepare Hash required
                            vb_login_md5password_utf = GetMD5HASH(CHRTOUTF8$(password))       'UTF8 Prepare Hash required
                        
                            pWHttp.Open "GET", "https://forum.powerbasic.com/auth/login-form", %false
                            pWHttp.Send
                            iSucceeded = pWHttp.WaitForResponse(5)
                        
                            wsHeaders = FORMAT$(pWHttp.Status) + " " + pWHttp.Statustext + $CRLF        'extract Cookies from Header
                            wsHeaders += pWHttp.GetAllResponseHeaders
                            'MSGBOX wsHeaders                                                            'used for tracking --- not needed comment or delete
                        
                            CookiesCnt = TALLY(wsHeaders, "Set-Cookie: ")
                            REDIM Cookies(1 TO CookiesCnt)
                            lCount2 = 0
                            FOR lCount1 = 1 TO PARSECOUNT(wsHeaders, $CRLF)
                              wTemp1 = PARSE$(wsHeaders, $CRLF, lCount1)
                              IF TALLY(wTemp1, "Set-Cookie: ") = 1 THEN
                                   lCount2 += 1
                                   wTemp1 = PARSE$(wTemp1, ";", 1)
                                   Cookies(lCount2) = REMOVE$(wTemp1, "Set-Cookie: ")
                              END IF
                            NEXT lCount1
                        
                            ' Now Prepare and send a POST Request
                            pWHttp.Open "POST", "https://forum.powerbasic.com/auth/login", %false         ' Point to proper link for posting payload
                            pWHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded; " ' Payload is urlencoded so this needed so server decodes it correctly
                        
                              FOR lCount1 = 1 TO CookiesCnt                           'Put Cookies collected in previous Get request to this Post Request Header
                               wsCookies +=  Cookies(lCount1)+"; "                    '
                              NEXT lCount1                                            '
                               wsCookies = TRIM$(wsCookies, "; ")                     '
                               'MSGBOX wsCookies                                       '
                            pWHttp.setRequestHeader "Cookie", wsCookies               '
                        
                           'Prepare Payload Based on Username and Password Above other values are Static
                           vBody="url=aHR0cHM6Ly9mb3J1bS5wb3dlcmJhc2ljLmNvbQ%3D%3D&username="+ username + _
                                 "&password=&rememberme=on&vb_login_md5password=" + vb_login_md5password + _
                                 "&vb_login_md5password_utf=" + vb_login_md5password_utf
                        
                            pWHttp.setRequestHeader "Content-Length", FORMAT$(LEN(VARIANT$(vBody)))      ' Size of Payload also needed
                        
                            pWHttp.Send vBody                                                      ' Send POST Request
                        
                            ' Wait for response with a timeout of 5 seconds
                            iSucceeded = pWHttp.WaitForResponse(5)
                            wsHeaders = FORMAT$(pWHttp.Status) + " " + pWHttp.Statustext + $CRLF
                            wsHeaders += pWHttp.GetAllResponseHeaders
                            'MSGBOX wsHeaders
                        
                            CookiesCnt = TALLY(wsHeaders, "Set-Cookie: ")
                            REDIM Cookies(1 TO CookiesCnt)
                            lCount2 = 0
                            FOR lCount1 = 1 TO PARSECOUNT(wsHeaders, $CRLF)
                              wTemp1 = PARSE$(wsHeaders, $CRLF, lCount1)
                              IF TALLY(wTemp1, "Set-Cookie: ") = 1 THEN
                                   lCount2 += 1
                                   wTemp1 = PARSE$(wTemp1, ";", 1)
                                   Cookies(lCount2) = REMOVE$(wTemp1, "Set-Cookie: ")
                                   IF TALLY (Cookies(lCount2), "vb3187userid") = 1 THEN vb_UserID = Cookies(lCount2)           ' these are the magic cookies that ID you
                                   IF TALLY (Cookies(lCount2), "vb3187password") = 1 THEN vb_PassHash = Cookies(lCount2)       ' with these you dont need to perform the
                              END IF                                                                                           ' login sequence above
                            NEXT lCount
                          END IF 'phase1   end first request
                        
                            'OK we have what we need now fetch the image
                            pWHttp.Open "GET", OnlineImageURL , %false
                            pWHttp.setRequestHeader "Cookie", wsCookies + "; " + vb_UserID + "; " + vb_PassHash
                        
                            pWHttp.Send
                        
                            ' Wait for response with a timeout of 5 seconds
                            iSucceeded = pWHttp.WaitForResponse(5)
                        
                           IF iSucceeded THEN
                            wsHeaders = FORMAT$(pWHttp.Status) + " " + pWHttp.Statustext + $CRLF
                            wsHeaders += pWHttp.GetAllResponseHeaders
                            MSGBOX wsHeaders
                        
                            if pWHttp.Status <> 200 then exit function ' failed to get what we asked for.
                        
                            FOR lCount1 = 1 TO PARSECOUNT(wsHeaders, $CRLF)               ' extract Filename from header
                              wTemp1 = PARSE$(wsHeaders, $CRLF, lCount1)
                              IF TALLY(wTemp1, "filename=") = 1 THEN
                                FOR lCount2 = 1 TO PARSECOUNT(wTemp1, ";")
                                 wFilename = PARSE$(wTemp1, ";", lCount2)
                                 IF TALLY (wFilename, "filename=") = 1 THEN wFilename = REMOVE$(wFilename, "filename=") : EXIT FOR : EXIT FOR
                                NEXT lCount2
                              END IF
                            NEXT lCount
                            wFilename = TRIM$(wFilename,ANY $DQ+$SPC)
                            'MSGBOX wFilename
                        
                            ' Get the response as a stream
                             vStream = pWHttp.ResponseStream
                            IF VARIANTVT(vStream) = %VT_UNKNOWN THEN
                               pIStream = vStream
                               vStream = EMPTY
                               ' Read the stream in chunks
                               DO
                                  pIStream.Read VARPTR(buffer), SIZEOF(buffer), cbRead
                                  IF cbRead = 0 THEN EXIT DO
                                  IF cbRead < SIZEOF(buffer) THEN
                                     strBuffer = strBuffer & LEFT$(buffer, cbRead)
                                  ELSE
                                     strBuffer = strBuffer & buffer
                                  END IF
                               LOOP
                               pIStream = NOTHING
                               IF LEN(strBuffer) THEN
                                  'MSGBOX strBuffer
                                  ' Save the buffer into a file
                                  IF LocalImageURL <> "" THEN wFilename = LocalImageURL
                                  IF wFilename = "" THEN wFilename = "My-image.html"
                                  IF ISFILE (wFilename) THEN KILL wFilename
                                  OPEN wFilename FOR BINARY AS #1
                                  PUT #1, 1, strBuffer
                                  CLOSE #1
                                  'MSGBOX "File saved"
                                  FUNCTION = %true
                               ELSE
                                  MSGBOX "Buffer is empty"
                               END IF
                            END IF
                           END IF
                         CATCH
                           OleShowErrorInfo OBJRESULT
                         END TRY
                        
                        END FUNCTION
                        ' ========================================================================================
                        
                        FUNCTION GetMD5HASH(BYVAL strText AS STRING) AS STRING
                           REGISTER i AS LONG
                           LOCAL hHash AS DWORD, hText AS STRING
                           LOCAL hProv AS DWORD, strHash AS STRING * 16, strHashPtr AS BYTE PTR
                        
                          'md5 initialization
                           IF GetCSPHandle(hProv) < 2 THEN
                              IF hProv THEN CryptReleaseContext hProv, 0
                           END IF
                           strHashPtr = VARPTR(strHash)
                        
                           CryptCreateHash(hProv, %CALG_MD5, 0, 0, hHash )
                           CryptHashData(hHash, BYVAL STRPTR(strText), LEN(strText), 0)
                           CryptGetHashParam(BYVAL hHash, BYVAL %HP_HASHVAL, BYVAL strHashPtr, 16, 0)
                           CryptDestroyHash hHash
                        
                           FOR i = 0 TO 15
                              hText += HEX$( @strHashPtr[i], 2 )
                           NEXT
                           FUNCTION = LCASE$(hText)
                        END FUNCTION
                        
                        FUNCTION GetCSPHandle(hCSP AS DWORD) AS LONG
                           IF CryptAcquireContext( hCSP, BYVAL %Null, BYVAL %Null, %PROV_RSA_AES, 0 ) = %False THEN
                              ' Unable To Find a Default For %PROV_RSA_AES so force the issue first For Vista And above
                              IF CryptAcquireContext( hCSP, BYVAL %Null, $MS_ENH_RSA_AES_PROV_A, %PROV_RSA_AES, %CRYPT_VERIFYCONTEXT ) = %False THEN
                                 ' Still failed so force the issue With XP SP3
                                 IF CryptAcquireContext( hCSP, BYVAL %Null, $MS_ENH_RSA_AES_PROV_XP_A, %PROV_RSA_AES, %CRYPT_VERIFYCONTEXT ) = %False THEN
                                    ' Stll failed so Try And Find a Default For < XP SP3
                                    IF CryptAcquireContext( hCSP, BYVAL %Null, BYVAL %Null, %PROV_RSA_FULL, 0 ) = %FALSE THEN
                                       ' Unable To Find a Default For %PROV_RSA_FULL failed so force the issue
                                       IF CryptAcquireContext( hCSP, BYVAL %Null,$MS_DEF_PROV_A, %PROV_RSA_FULL, %CRYPT_VERIFYCONTEXT ) = %FALSE THEN
                                          FUNCTION = 0
                                       ELSE
                                          FUNCTION = 1 ' < XP SP3
                                       END IF
                                    ELSE ' found Default %PROV_RSA_FULL
                                       FUNCTION = 1
                                    END IF
                                 ELSE
                                    FUNCTION = 2 ' XP SP3
                                 END IF
                              ELSE
                                 FUNCTION = 3 ' Vista And above
                              END IF
                           ELSE ' found Default %PROV_RSA_AES
                              FUNCTION = 3
                           END IF
                        END FUNCTION

                        Comment


                        • #13
                          Rod!
                          Thanks very much. I'll be out most of the day but will digest you post this evening. I'm sure to have questions!

                          Comment


                          • #14
                            Another design decision is needed. I almost always do a "word" search, not a "string search'. The string search looks for multi-word phrases like "SQL Tutorial" vs a thread that has both SQl and tutorial in it.

                            Options:
                            1. Drop the string search completely and cut the index files count/size in half
                            2. Keep the string search and do a real-time extraction of the HMTL text (which is used for the string search). Slows down a string search substantially.
                            3. Keep the string search and pre-extract the HTML text. Faster string search but adds 0.5GB to the required index files.

                            I'd prefer #2, keep the string search for the occasional need but accept a slower string search in order to reduce the overall file size requirements.

                            But, I'm open to feedback on the topic.

                            Comment


                            • #15
                              4. Option to only create index if wanted, but have no idea if you are considering SQLite.
                              5. Mentioned full text search FTS (like Google) in another thread (might be an option in another version.) https://www.sqlite.org/fts5.html
                              Some might even like to use the search abilities of NotePad ++ (or others) integrated as an option.
                              6. Option to
                              Code:
                               shellexecute  site:powerbasic.com  search string
                              https://duckduckgo.com instead of google

                              Comment


                              • #16
                                Dear Gary,
                                I upgraded from PBWIN8 to PBWIN10 and have some problems to run a program in the enclosure.
                                Nothing is printed using PBWIN10. Using PBWIN8 al is ok.
                                This is a letter header with pictures and text from a file: All together should be printed out.
                                Can you / anybody help me please to start this programm with PBWIN10, please?

                                code here:
                                'briefkopfdrucken.bas Stand: 14.11.2006 ufb!!! f. RHO
                                ' Falzkante eingefügt: ok!!
                                #COMPILE EXE
                                $DIM ALL
                                $INCLUDE "win32api.inc" 'pb=Paperbreite in pkt.
                                GLOBAL nfile&, Datumheute$, Datum$, xp AS LONG, winxp AS LONG, winver$, cm AS LONG, pb AS LONG

                                'vorgegebene Funktion: cm in ppi umwandeln
                                FUNCTION CM2PPI(cXY AS STRING ,nCM AS SINGLE) AS SINGLE
                                LOCAL x&, y&
                                XPRINT GET PPI TO x&, y&
                                SELECT CASE cXY
                                CASE "x","X"
                                CM2PPI = nCM * x& / 2.54
                                CASE "y","Y"
                                CM2PPI = nCM * y& / 2.54
                                CASE ELSE
                                CM2PPI = 0
                                END SELECT
                                END FUNCTION

                                'vorgegebene Funktion: ppi in cm umwandeln
                                FUNCTION PPI2CM(cXY AS STRING ,nPoints AS SINGLE) AS SINGLE
                                LOCAL x&, y&
                                XPRINT GET PPI TO x&, y&
                                SELECT CASE cXY
                                CASE "x","X"
                                PPi2CM = nPoints / x& * 2.54
                                CASE "y","Y"
                                PPi2CM = nPoints / y& * 2.54
                                CASE ELSE
                                PPi2CM = 0
                                END SELECT
                                END FUNCTION

                                'vorgegebene Funktion: ppi in mm umwandeln
                                FUNCTION PPI2MM(cXY AS STRING ,nPoints AS SINGLE) AS SINGLE
                                PPi2MM = PPI2CM(cXY,nPoints) * 10
                                END FUNCTION


                                'vorgegebene Funktion: Betriebssystem feststellen:


                                ' ab hier beginnt die eigene Entwicklerarbeit: heutiges Datum ins richtige Format setzen:
                                SUB HeuteDatum
                                LOCAL tag AS STRING
                                LOCAL month AS STRING
                                tag=MID$(DATE$,4,2)
                                month=LEFT$(DATE$,2)
                                IF LEFT$(month,1)="0" THEN
                                month=RIGHT$(month,1)
                                END IF
                                Datumheute$=tag+". "+month+". "+RIGHT$(DATE$,4)
                                Datum$=Datumheute$
                                END SUB

                                ' hier wird die Seite aufgebaut und gedruckt:
                                FUNCTION XPrintText( sText AS STRING, sHeader AS STRING, sFont AS STRING, fSize AS LONG, fStyle AS LONG ) AS LONG

                                LOCAL sPrint, sLine, sTemp AS STRING
                                LOCAL i, j, Count, PageLines, Page, POS, hFile, LastPos AS LONG
                                LOCAL nLeft, nTop, nRight, nBottom, PageWidth, PageHeight, TxtWidth, TxtHeight AS SINGLE
                                LOCAL x, y, PrntMargin AS SINGLE
                                LOCAL nwidth&, nheight& , a AS LONG , b AS LONG , c AS LONG, ncWidth!, ncHeight!

                                'einen Drucker zuweisen
                                XPRINT ATTACH CHOOSE
                                IF LEN(XPRINT$) = 0 THEN
                                FUNCTION = 0
                                EXIT FUNCTION ' Druckerfehler !?
                                ELSE
                                i = MSGBOX( XPRINT$+$CRLF+$CRLF+$CRLF+"Diesen Drucker verwenden?",%MB_YESNO ,"eingestellter Drucker")
                                IF i = %IDNO THEN
                                XPRINT CLOSE
                                XPRINT ATTACH CHOOSE
                                IF LEN(XPRINT$) = 0 THEN
                                MSGBOX "es wurde kein Drucker ausgewählt!",64,"Druckerauswahl Error"
                                EXIT FUNCTION
                                END IF
                                END IF
                                END IF
                                '================================ Papier- und Seiteneinstellungen für den Ausdruck:
                                XPRINT GET CLIENT TO ncWidth!, ncHeight!
                                XPRINT SCALE (0,0)-(210,297) ' alle Werte in mm angeben, wohin gedruckt werden soll! Hochformat!
                                'get page specs
                                XPRINT FONT sFont, fSize, fStyle ' set the font first
                                XPRINT GET LINES TO PageLines ' 57 MSGBOX STR$(PageLines),64,"PageLines"
                                XPRINT GET MARGIN TO nLeft, nTop, nRight, nBottom 'get margins
                                XPRINT GET CLIENT TO PageWidth, PageHeight 'get print area
                                PrntMargin = PageWidth * 0.06 ' MSGBOX STR$(PrntMargin),64,"PrntMargin"
                                PageWidth = PageWidth - ( PrntMargin*2 ) ' MSGBOX STR$(PageWidth),64,"PageWidth"
                                '================================
                                ' pb=pagewidth/137.71 ' pagewidth=6464 "Punkte" ----- pb= 21 cm
                                ' cm=pb*137.71/21 ' Höhe = 137,71 Punkte/cm
                                ' msgbox str$(cm)+" = Punkte pro cm"
                                '============================================================================
                                'break up long lines *** hier: vorgegebene Routine zur Textpositionierung:
                                sPrint = ""
                                FOR i = 1 TO PARSECOUNT( sText, $CRLF ) ' go thru the whole file
                                sLine = PARSE$( sText, $CRLF, i ) ' get string that is too long
                                XPRINT TEXT SIZE sLine TO TxtWidth, TxtHeight ' get length of line
                                IF TxtWidth > PageWidth THEN ' the line is longer than the page width
                                POS = INSTR( 1, sLine, " " ) ' find first word
                                WHILE LEN(sLine)
                                POS = INSTR( 1, sLine, " " ) ' find the end of the first word
                                DO ' step thru the line word by word
                                LastPos = POS ' save last step
                                POS = INSTR( POS+1, sLine, " " ) ' next word
                                sTemp = LEFT$( sLine, POS-1 ) ' load line so far
                                XPRINT TEXT SIZE sTemp TO TxtWidth, TxtHeight ' get length of line so far
                                IF POS = 0 THEN ' at the end of the line
                                IF TxtWidth > PageWidth THEN ' we have a very long word!
                                IF LastPos THEN EXIT LOOP ' end of line and PageWidth coincide
                                DO ' loop thru the word one char at a time
                                INCR POS
                                sTemp = LEFT$( sLine, POS ) ' compile word
                                XPRINT TEXT SIZE sTemp TO TxtWidth, TxtHeight ' Test length
                                LastPos = POS ' Last Char is under PageWidth
                                LOOP UNTIL TxtWidth >= PageWidth ' Exit when Pagewidth exceeded
                                EXIT LOOP ' Done
                                ELSE
                                LastPos = LEN(sLine)+1 ' Line is shorter than PageWidth
                                EXIT LOOP ' Done
                                END IF
                                END IF
                                LOOP UNTIL TxtWidth > PageWidth ' now line is one step too long
                                sTemp = LEFT$( sLine, LastPos-1 ) ' Line at last step befor exceded PageWidth
                                sPrint = sPrint + TRIM$(sTemp) + $CRLF ' Add correct length line to lines so far
                                sLine = RIGHT$( sLine, -(LastPos-1) ) ' Remove from line and continue on (PB8)
                                POS = 1 ' start at beggining of what is left of line
                                WEND
                                ELSE
                                sPrint = sPrint + TRIM$(sLine) + $CRLF ' Line length is less than Page Width
                                END IF
                                NEXT i ' repeat for all lines in sText
                                sPrint = RTRIM$( sPrint, $CRLF ) ' Remove trailing $CRLF's
                                '================================


                                ' OPEN "FormattedLetter.txt" FOR BINARY AS #hFile ' for testing
                                ' IF ERR THEN
                                ' MSGBOX "Problem creating file",64,"File Error"+STR$(ERRCLEAR)
                                ' CLOSE #hFile
                                ' EXIT FUNCTION
                                ' END IF
                                ' PUT$ #hFile, sPrint
                                ' CLOSE #hFile
                                ' EXIT FUNCTION
                                ' '================================


                                'print header Logo ganz oben ajuf der ausgedruckten Seite: Bilder und Schrift
                                Page = 1 : a = 230 ' um ... Punkte tiefer! a = 230
                                sHeader="Holiday-Inn" '
                                XPRINT TEXT SIZE sHeader TO TxtWidth, TxtHeight ' Header width
                                ' MSGBOX STR$(TxtWidth) + " " + STR$(TxtHeight)
                                XPRINT COLOR RGB(3,135,63), -2
                                XPRINT FONT "Comic Sans MS",26,3
                                XPRINT SET POS (60, 25)
                                XPRINT sHeader

                                sHeader="Mary"
                                XPRINT FONT "Comic Sans MS",12,3
                                XPRINT SET POS (63, 36)
                                XPRINT sHeader

                                sHeader="and"
                                XPRINT FONT "Comic Sans MS",10,3
                                XPRINT SET POS (67, 41)
                                XPRINT sHeader

                                sHeader="Rudolf"
                                XPRINT FONT "Comic Sans MS",12,3
                                XPRINT SET POS (75,41)
                                XPRINT sHeader

                                sHeader="name"
                                XPRINT FONT "Comic Sans MS",24,3
                                XPRINT SET POS (92, 36)
                                XPRINT sHeader

                                b = 0 'senkrechte Verschiebung: nach oben o. unten: -/+ für Testzwecke benutzt!
                                sHeader="street nr, city"
                                XPRINT FONT "Comic Sans MS",13,3
                                XPRINT SET POS (136,50 )
                                XPRINT sHeader
                                sHeader="Tel./Fax: +49xxxx"
                                XPRINT FONT "Comic Sans MS",13,3
                                XPRINT SET POS (136, 56)
                                XPRINT sHeader
                                sHeader="www.xxx-yyy.de"
                                XPRINT FONT "Comic Sans MS",11,3
                                XPRINT SET POS (136, 62)
                                XPRINT sHeader
                                sHeader="email: [email protected]"
                                XPRINT FONT "Comic Sans MS",11,3
                                XPRINT SET POS (136, 67)
                                XPRINT sHeader
                                sHeader=Datum$
                                XPRINT FONT "Comic Sans MS",12,3 ' Datum:
                                XPRINT COLOR RGB(0,0,0),-1
                                XPRINT SET POS (150, 80)
                                XPRINT sHeader
                                ' Falzkante markieren: kurze Linie am linken Rand
                                XPRINT WIDTH 4
                                ' XPRINT FONT "Comic Sans MS",11,3
                                XPRINT LINE (0, 108) - (9, 108)
                                '================================
                                ' drucke BMP:
                                nfile&=FREEFILE
                                OPEN "pic1.bmp" FOR BINARY AS nfile&
                                GET #nFile&, 19, nwidth&
                                GET #nFile&, 23, nHeight&
                                CLOSE nFile&
                                XPRINT RENDER "pic1.bmp", (5,5)-(50,47)
                                IF ERR THEN MSGBOX "Status von XPRINT RENDER" + STR$(ERRCLEAR)
                                '================================ Mitte: Logo familyv.bmp
                                nfile&=FREEFILE
                                OPEN "pic2.bmp" FOR BINARY AS nfile&
                                GET #nFile&, 19, nwidth&
                                GET #nFile&, 23, nHeight&
                                CLOSE nFile&
                                XPRINT RENDER "pic2.bmp", (54,5)-(160,27)
                                IF ERR THEN MSGBOX "Status von XPRINT RENDER" + STR$(ERRCLEAR)
                                '================================ Rechts: brommi_rh_col.bmp

                                nfile&=FREEFILE
                                OPEN "pic3.bmp" FOR BINARY AS nfile&
                                GET #nFile&, 19, nwidth&
                                GET #nFile&, 23, nHeight&
                                CLOSE nFile&
                                XPRINT RENDER "pic3.bmp", (165,5)-(206,44)
                                IF ERR THEN MSGBOX "Status von XPRINT RENDER" + STR$(ERRCLEAR)
                                '================================
                                ' Umrahmen mit: ¤ :
                                ' XPRINT COLOR RGB(63,135,63), -2
                                ' XPRINT FONT "Comic Sans MS",10,3
                                ' XPRINT SET POS (50, 24)
                                ' XPRINT string$(150, "~")
                                ' .......... oberer Rand ........................... unterer Rand: blaue Wellenlinie
                                XPRINT COLOR RGB(7,146,248), -2
                                ' XPRINT FONT "Comic Sans MS",10,3
                                XPRINT SET POS (5, 45)
                                XPRINT STRING$(48, "~")
                                ' allgemeine Druckfarbe festlegen für restlichen Ausdruck:
                                XPRINT COLOR RGB(0,0,0),-1
                                XPRINT FONT "Comic Sans MS",8,5
                                XPRINT SET POS (17, 50)
                                XPRINT "Addr.: Ferienhof name, street nr, city"
                                ' XPRINT FONT "Comic Sans MS",11,3
                                XPRINT FONT "Comic Sans MS",11,3 ' Schriftgröße für restlichen Brieftext
                                '.........................................................................................
                                'Print the pages line by line
                                ' Count = 4 ' 4 lines for header
                                XPRINT GET POS TO x, y :y=600
                                FOR i = 1 TO PARSECOUNT( sPrint, $CRLF )
                                INCR Count
                                XPRINT GET POS TO x, y
                                y=y/10+5*i
                                ' msgbox str$(x)+ ", "+str$(y)
                                ' XPRINT SET POS (PrntMargin+120, y ) ' move print start position to calculated margin
                                XPRINT SET POS (PrntMargin+5, y )
                                sLine = PARSE$( sPrint, $CRLF, i )
                                XPRINT sLine
                                IF Count = PageLines THEN
                                INCR Page
                                XPRINT FORMFEED ' New page
                                XPRINT TEXT SIZE sHeader TO TxtWidth, TxtHeight ' Header width
                                ' XPRINT SET POS (PrntMargin+120, nTop+TxtHeight )
                                XPRINT SET POS (PrntMargin+5, nTop+TxtHeight )
                                XPRINT "Seite " + FORMAT$(Page, "0")
                                XPRINT SET POS (((PageWidth-TxtWidth)/2), nTop+TxtHeight )
                                XPRINT sHeader
                                XPRINT
                                ' Count = 4
                                END IF
                                NEXT i
                                '================================

                                ' ab zum Druck!!
                                'Detach the printer
                                XPRINT CLOSE
                                '================================

                                FUNCTION = Page ' return # of pages printed

                                END FUNCTION

                                '¤¤¤¤¤¤¤¤¤¤¤¤¤ Hauptroutine
                                FUNCTION PBMAIN

                                LOCAL i, hFile AS LONG
                                LOCAL sFile, sLine, sTemp AS STRING

                                ' feststellen, welches Betriebssystem: bei WINXP einen "Vergrößerungsfaktor anwenden: winxp=1.66
                                ' winver$= osversion winxp ist hier eigentlich unnötig, diente für frühere Versuche,
                                ' da bei unterschiedlichen Systemen die Bildgröße verschieden groß ausgedruckt wurde


                                ' aktuelles Datum in Bestätigung einfügen
                                CALL heutedatum
                                ' nun schreibe den aktuellen Bestätigungstext mit der zugehörigen Anschrift des Gastes:
                                hFile = FREEFILE '
                                OPEN "fewobesx.txt" FOR BINARY AS hFile ' < bessere Technik als unten
                                ' OPEN "fewobesx.txt" AS hFile ' veraltet
                                IF ERR THEN
                                MSGBOX "Problem mit dem Öffnen des Files",64,"File Error"+STR$(ERRCLEAR)
                                CLOSE hFile
                                EXIT FUNCTION
                                END IF
                                GET$ hFile, LOF(hFile), sFile ' read the whole file into a string
                                CLOSE hFile
                                '================================

                                i = XPrintText( sFile, "", "Comic Sans MS", 12, 0 ) ' Print the text
                                IF i THEN
                                ' MSGBOX STR$(i)+" Seiten gedruckt",64,"Ausdruck komplett"
                                ELSE
                                MSGBOX "Nichts wurde gedruckt",64,"Druck fehlgeschlagen!"
                                END IF
                                '================================
                                END FUNCTION
                                '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
                                Attached Files

                                Comment


                                • #17
                                  Hey Mike!

                                  I am considering SQLite but my window of opportunity to make an update is about to close. So anything related to SQLite will have to wait for a future revision. I'm keeping my code as compartmentalized as possible so that I can change pieces of it with new strategies. Even so, I suspect SQLite will break a lot of my existing code - which is okay it the results are beneficial.

                                  As you suggest, I will include an option for the user to optionally create a single file that contains the text from all threads. Users who want it can then open that file in their editor of choice and use that editor's search features. The file size will be about 500MB. I need that file for string search, so depending on whether I include that feature, the file may be there anyway.

                                  The opening of an external site: search is a good idea and quite easy to implement. I'll add that feature. For back-to-back searches, it might be a bit awkward flipping back and forth between gbThreads and the browser but will still be worth having.

                                  Thanks for the suggestions!

                                  Comment


                                  • #18
                                    Has anyone ever used the option to change the colors used to display the list of threads in the ListView? I've never done that.

                                    Unless asked otherwise, I'll have an option to use the default colors or black. No options to customize the colors.

                                    Same is true for syntax highlighting code. The new gbThreads will use syntax highlighting with default colors or black. No options to customize the colors.

                                    Comments welcome.

                                    Comment


                                    • #19
                                      I learned early on from users that one should never tamper with system colors, because people can do that themselves via Windows "Personalize" settings ("Themes") and some people with bad eyesight like to use high contrast color schemes, etc.

                                      Comment


                                      • #20
                                        Howdy, Borje!

                                        Yes, I completely agree. I'm only speaking of using code within Case %NM_CustomDraw to change the colors of text within each ListView column - optional, of course!

                                        I deal a lot with folks who have macular degeneration and they do indeed modify their Windows settings in an attempt to make things more readable. Most users find the Windows ease-of-access tools helpful, but also very insufficient. There is a whole market of software out there, particularly JAWS and ZoomText, that attempt to enable low-vision users to more easily use computers.

                                        Comment

                                        Working...
                                        X