Page 1 of 2

Parse for web link in text string

Posted: Thu Nov 09, 2006 5:42 am
by rsts
Hard to believe this hasn't already been done, but maybe my search skills have failed me yet again.

I'm looking to recognize links in a text string and highlight them in an editor gadget to provide a user mechanism to launch them in a browser via ShellExecute_. I know that they're recognized in a web gadget but was looking for a way to recognize them in an editor.

Probably not a tremendous deal to write one, just wondering if it's already been done or if anyone knows of an API to accomplish it.

cheers

Posted: Thu Nov 09, 2006 11:32 am
by dell_jockey
rsts,

a couple of weeks ago I had a similar need (URL's & email addresses), but didn't implement it (and consequently got side-tracked...).
I did make some notes though, about implementing this using regular expressions to filter out an URL, as a regex would allow to refactor similar stuff done in Perl and other script languages that are used on the web. There is a regex lib available for PB somewhere, just search the forum.

Re: Parse for web link in text string

Posted: Thu Nov 09, 2006 12:17 pm
by gnozal
rsts wrote:Hard to believe this hasn't already been done, but maybe my search skills have failed me yet again.

I'm looking to recognize links in a text string and highlight them in an editor gadget to provide a user mechanism to launch them in a browser via ShellExecute_. I know that they're recognized in a web gadget but was looking for a way to recognize them in an editor.

Probably not a tremendous deal to write one, just wondering if it's already been done or if anyone knows of an API to accomplish it.
I have no experience with an EditorGadget (RichEdit) but it works well with the Scintilla control (see jaPBe V3 sources).
I 'simply' detect the 'http://...' string in the editor text during the syntax coloring process and then I set a special 'URL' style with the 'HotSpot' property. When the user clicks on the hotspot, scintilla generates a special event so I can start the browser.

Posted: Thu Nov 09, 2006 5:16 pm
by Trond
Something with #CFM_LINK (=$00000020) and #ENM_LINK (=$04000000)?

Posted: Thu Nov 09, 2006 6:00 pm
by rsts
Trond wrote:Something with #CFM_LINK (=$00000020) and #ENM_LINK (=$04000000)?
That's worth investigating. Thanks. :)

Have you used it, by any chance?

cheers

Posted: Thu Nov 09, 2006 6:50 pm
by freak
Try this:

Code: Select all

#ENM_LINK = $04000000
#CFM_LINK = $00000020
#EN_LINK  = 1803

Procedure Callback(Window, Message, wParam, lParam)

  ; WM_NOTIFY can only be caught in the callback, not in the main loop
  ;
  If Message = #WM_NOTIFY
    *hdr.NMHDR = lParam    
   
    ; ensure it is the right message and gadget
    ;     
    If *hdr\hwndFrom = GadgetID(0) And *hdr\code = #EN_LINK
      *link.ENLINK = lParam
    
      ; react only to the button release part.
      ;
      If *link\msg = #WM_LBUTTONUP
      
        ; Show also the range of text that was clicked
        ;
        MessageRequester("", "click! (" + Str(*link\chrg\cpMin) + ", " + Str(*link\chrg\cpMax) + ")")
      EndIf
      
    EndIf    
  EndIf

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 400, 400, "Links", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  CreateGadgetList(WindowID(0))
  SetWindowCallback(@Callback())  
  EditorGadget(0, 10, 10, 380, 380)
    
  ; Enable the link message
  SendMessage_(GadgetID(0), #EM_SETEVENTMASK, 0, #ENM_LINK)
  
  ; This enables autodetect of url text
  ; must be before the SetGadgettext.
  SendMessage_(GadgetID(0), #EM_AUTOURLDETECT, #True, 0)
  
  SetGadgetText(0, "There is a link in here." + Chr(13) + "http://www.purebasic.com/")
  
  ; To manually set a text as an url, select it and use the charformat message:    
  format.CHARFORMAT2\cbSize = SizeOf(CHARFORMAT2)
  format\dwMask = #CFM_LINK
  format\dwEffects = #CFM_LINK
  SendMessage_(GadgetID(0), #EM_SETSEL, 11, 15)  
  SendMessage_(GadgetID(0), #EM_SETCHARFORMAT, #SCF_SELECTION, @format)
  
  ; deselect the text
  SendMessage_(GadgetID(0), #EM_SETSEL, 0, 0)

  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow  
EndIf

Posted: Thu Nov 09, 2006 7:23 pm
by netmaestro
Dammit, beaten to the punch!

Code: Select all

Procedure CallBack(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  If msg = #WM_NOTIFY 
    *nc.ENLINK = lparam 
    If *nc\nmhdr\code = 1803 ; en_link 
      If *nc\wparam ; 1 indicates click event
        SendMessage_(*nc\nmhdr\hwndfrom, #EM_EXSETSEL, 0,*nc\chrg) 
        buf.s = Space(#MAX_PATH) 
        SendMessage_(*nc\nmhdr\hwndfrom, #EM_GETSELTEXT,0,@buf) 
        RunProgram(buf) 
      EndIf 
    EndIf 
  EndIf 
  ProcedureReturn result 
EndProcedure  

OpenWindow(0,0,0,640,480,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
SetWindowCallback(@CallBack()) 
eg=EditorGadget(0,0,0,640,480) 

SendMessage_(eg,#EM_SETEVENTMASK,0,$04000000) ; enm_link 
SendMessage_(GadgetID(0), #EM_AUTOURLDETECT, 1, 0) 

AddGadgetItem(0,-1, "Hello rsts, how are you today? ") 
AddGadgetItem(0, -1, "Would you like To visit http://www.lloydsplace.com on this fine day?") 
AddGadgetItem(0, -1, "There are certainly more boring things to do!") 
Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow

Posted: Thu Nov 09, 2006 7:41 pm
by srod
netmaestro wrote:Dammit, beaten to the punch!
:)

I was beaten as well - by about 2 minutes!

Must be getting slow in my old age! 8)

Posted: Thu Nov 09, 2006 7:43 pm
by netmaestro
Well, post yours anyway, it's probably better than mine.

Posted: Thu Nov 09, 2006 7:44 pm
by rsts
Old age? Hmmm - maybe that's why I'm "slow"?

Thanks guys, let me see what I can make out of these.

cheers

Posted: Thu Nov 09, 2006 7:45 pm
by freak
haha, i win! whats the price? :)

Posted: Thu Nov 09, 2006 7:49 pm
by netmaestro
I'll donate a slice of pizza and send it out right away parcel post. It should arrive in about 2-3 weeks. Congratulations!

Posted: Thu Nov 09, 2006 7:57 pm
by srod
I'm still waiting for the loose women that fangbeast promised!

I'll donate one of those as a prize if you like? :)

@netmaestro: unable to post as I deleted it on seeing that Freak's did everything that mine did - and more. All mine did was intercept a link click in an editor gadget and redirect a web gadget accordingly. Nothing fancy.

Posted: Fri Feb 06, 2009 5:48 pm
by ar-s
netmaestro wrote:Dammit, beaten to the punch!

Code: Select all

Procedure CallBack(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  If msg = #WM_NOTIFY 
    *nc.ENLINK = lparam 
    If *nc\nmhdr\code = 1803 ; en_link 
      If *nc\wparam ; 1 indicates click event
        SendMessage_(*nc\nmhdr\hwndfrom, #EM_EXSETSEL, 0,*nc\chrg) 
        buf.s = Space(#MAX_PATH) 
        SendMessage_(*nc\nmhdr\hwndfrom, #EM_GETSELTEXT,0,@buf) 
        RunProgram(buf) 
      EndIf 
    EndIf 
  EndIf 
  ProcedureReturn result 
EndProcedure  

OpenWindow(0,0,0,640,480,"",$cf0001) 
SetWindowCallback(@CallBack()) 
CreateGadgetList(WindowID(0)) 
eg=EditorGadget(0,0,0,640,480) 

SendMessage_(eg,#EM_SETEVENTMASK,0,$04000000) ; enm_link 
SendMessage_(GadgetID(0), #EM_AUTOURLDETECT, 1, 0) 

AddGadgetItem(0,-1, "Hello rsts, how are you today? ") 
AddGadgetItem(0, -1, "Would you like To visit http://www.networkmaestro.com on this fine day?") 
AddGadgetItem(0, -1, "There are certainly more boring things to do!") 
Repeat: Until WaitWindowEvent() = #WM_CLOSE
(another) Great code ! :D

When a link has been clicked in the editorgadget, how could we open it in a webgadget from the same program ?

Posted: Fri Feb 06, 2009 5:54 pm
by srod
Add a webgadget to the code and replace the RunProgram() with a SetGadgetText() directed at the webgadget.