Htm source editor with preview

Share your advanced PureBasic knowledge/code with the community.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

My thanks to the Team for fixing that 'internal server error', finally made me able to post my original code here. Thanks. :)
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post by zapman* »

Hello Utopiomania

Thanks for sharing !

I got an "invalid memory error" at the end of the "ReLoadSaveCallback" proc, while trying to open a big file. I had to transform your Read/Write procedures as follow:

Code: Select all

;Utility procedures 
Procedure ReLoadSaveCallback(LenF, *pbBuff, Cb, *Pcb.LONG)
  ;Callback used by ReSave/ReLoad 
  If LenF = 0 
    ;Save    
    WriteData(FileH, *pbBuff, Cb) 
    *Pcb\l = Cb 
  Else 
    ;Load 

    If LenF > Cb
      *Pcb\l = ReadData(FileH, *pbBuff, Cb) ; *Pcb while contain the real read length (which is not, in some case, the "expected" one)
    Else 
      *Pcb\l = ReadData(FileH, *pbBuff, LenF)
    EndIf 
  EndIf 
  ProcedureReturn 0 
EndProcedure 

Procedure ReLoad(Id, FileName.s, Rtf)
  ;RichEdit Load file
  LenF = FileSize(FileName)
  If LenF
    FileH = ReadFile(#PB_Any, FileName)
    
    If FileH And LenF
      Stream.EDITSTREAM 
      Stream\dwCookie    = LenF 
      Stream\pfnCallback = @ReLoadSaveCallback() 
      If Rtf 
        SendMessage_(GadgetID(Id), #EM_STREAMIN, #SF_RTF, @Stream) 
      Else 
        SendMessage_(GadgetID(Id), #EM_STREAMIN, #SF_TEXT, @Stream) 
      EndIf 
      CloseFile(FileH) 
      ResetModified(Id) 
    EndIf
  EndIf
EndProcedure 

Procedure ReSave(Id, FileName.s, Rtf) 
  ;RichEdit Save file 
  FileH = CreateFile(#PB_Any, FileName.s) 
  If FileH  
    Stream.EDITSTREAM 
    Stream\dwCookie    = 0 
    Stream\pfnCallback = @ReLoadSaveCallback() 
    If Rtf 
      SendMessage_(GadgetID(Id), #EM_STREAMOUT, #SF_RTF, @Stream) 
    Else 
      SendMessage_(GadgetID(Id), #EM_STREAMOUT, #SF_TEXT, @Stream) 
    EndIf 
    ResetModified(Id) 
    CloseFile(FileH) 
  EndIf 
EndProcedure 
and now, it works perfectly! I thinck that this version is more safe.

You shoulf perhaps update the code figuring on the first page of this topic?

Thanks.
Don't try - DO it !
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

Thanks, Zapman! I posted about that problem here:

http://www.purebasic.fr/english/viewtop ... ght=stream

and you fixed it so elegantly? Thanks! I'll update the code above. :)
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Re: Htm source editor with preview

Post by utopiomania »

Code: Select all

;-program notes
; PB4.10, 20080105, For PB (convert function)

;-initialise
;-
enumeration
  #WIN1
  #MENU
  #POP_UP
  #PANEL1
  #EDIT1
  #BUFFER
  #STAT1
  #WEB1
  #FILE_OPEN
  #FILE_INSERT
  #FILE_NEW
  #FILE_RECENT1
  #FILE_RECENT2
  #FILE_RECENT3
  #FILE_RECENT4
  #FILE_RECENT5
  #FILE_RECENT6
  #FILE_RECENT7
  #FILE_RECENT8
  #FILE_OPENCOPY
  #FILE_SAVE
  #FILE_SAVEAS
  #FILE_SAVETO
  #FILE_SAVECOPY
  #FILE_PRINT
  #FILE_HOME
  #FILE_EXPLORE
  #FILE_FIND
  #FILE_QUIT
  #EDIT_UNDO
  #EDIT_CUT
  #EDIT_COPY
  #EDIT_PASTE
  #EDIT_ERASE
  #EDIT_SELECTALL
  #EDIT_FINDREPL
  #EDIT_CONVERT
  #TOOLS_SEARCH1
  #TOOLS_SEARCH2
  #TOOLS_NOTEPAD
  #TOOLS_SYSMON
  #TOOLS_MAGNIFY
  #SETUP_TOPMOST
  #SETUP_SIZ1
  #SETUP_SIZ2
  #SETUP_SIZ3
  #SETUP_WDT1
  #SETUP_WDT2
  #SETUP_WDT3
  #SETUP_HGT1
  #SETUP_HGT2
  #SETUP_HGT3
  #SETUP_CUSTOM
  #SETUP_FONT
  #SETUP_COLOR
  #SETUP_DESKTOP
  #SETUP_STARTMENU
  #HELP_HTM
  #HELP_PDF
  #HELP_ABOUT 
endenumeration

declare openMainWindow()
declare disableMenuItems(id, first, last, true)
declare fileHome()
declare fileOpen()
declare saveRecentFiles(path.s)
declare fileInsert()
declare fileSave()
declare fileSaveAs()
declare fileSaveCopy()
declare fileSaveTo()
declare fileNew()
declare fileShutdown()
declare fileLogoff()
declare fileExit()
declare findReplace(id)

declare convertTostring()
declare setupFont()
declare helpAbout() 
declare about(parent, text.s, html.s) 

declare reLoad(id, name.s, rtf)
declare reSave(id, name.s, rtf)
declare reLoadSaveCallback(lenF, *pbBuff, cb, *pcb.LONG)

;linenumber callback and procedure
declare editCallback(hWnd, uMsg, wParam, lParam)
declare drawLinenumbers()

declare insertFile(id, path.s)
declare saveModifiedFile()
declare isModified()
declare resetModified()
declare savePreview()
declare loadPreview()
declare processCmdLine()
declare getLinenumber(id)
declare.s getprogramName(exeName.s)
declare readPreferences(inFolder.s, name.s)
declare writePreferences(inFolder.s, name.s)
declare setPreviewSize(wdt, hgt)
declare createShortcut(file, res.s, url.s, icon.s, index)
declare.s getSpecialFolder(id)

global appName.s, appFolder.s, preferences.s
appName = "html editor"
appFolder = appName + "\"

;preferences file
global inFolder.s, name.s
inFolder = appName
name = appName

global maximized, windowW, windowH
global untitled.s = "untitled.html"
global fileName.s = untitled
;separate default folders
global fileOpenFolder.s, fileInsertFolder.s
global fileSaveCopyFolder.s, fileSavetoFolder.s
global fontName.s, fontSize
global fontColor, backColor
;recent files menu items
global recent1.s, recent2.s, recent3.s, recent4.s
global recent5.s, recent6.s, recent7.s, recent8.s 

;used by reLoad/reSave/reLoadSaveCallback()
global lenF, fileH

;for linenumber callback and functions
global editProc, leftM = 48

;used by getSpecialFolder()
;..user\start menu\programs
#CSIDL_PROGRAMS = $2
;..user\desktop
#CSIDL_DESKTOPDIRECTORY = $10

;-program entry
readPreferences(inFolder, name)
openMainWindow()
processCmdLine()

;-program event handler
repeat
  event = waitWindowEvent()
  select event
    case #PB_EVENT_GADGET
      select eventGadget()
        case #PANEL1
          select getGadgetState(#PANEL1)
            case 0
              ;html file
              disablemenuItems(#MENU, #FILE_OPEN, #HELP_ABOUT, #FALSE)
              ;unload the preview
              setGadgetText(#WEB1, "about:")
              setActiveGadget(#EDIT1)
              statusBarText(#STAT1, 0, "  Licenced To: UNLICENCED") 
            case 1
              ;html preview
              if savePreview()
                disablemenuItems(#MENU, #FILE_OPEN, #FILE_EXPLORE, #TRUE)
                disablemenuItems(#MENU, #EDIT_UNDO, #EDIT_FINDREPL, #TRUE)
                loadPreview()
                setActiveGadget(#WEB1)
                wdt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
                hgt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
                statusBarText(#STAT1, 0, " Preview Size:  " + str(wdt) + " / " + str(hgt)) 
              else
                disableMenuItems(#MENU, #FILE_OPEN, #HELP_ABOUT, #FALSE)                
                setGadgetState(#PANEL1, 0)
                setActiveGadget(#EDIT1)
              endIf
          endSelect
      endSelect

;-\menu events
    case #PB_EVENT_MENU
      select eventMenu()
        case #PB_SHORTCUT_F5
          ;switch between tabs
          select getGadgetState(#PANEL1)
            case 0
              ;switch to html preview
              if savePreview()
                disablemenuItems(#MENU, #FILE_OPEN, #FILE_EXPLORE, #TRUE)
                disablemenuItems(#MENU, #EDIT_UNDO, #EDIT_FINDREPL, #TRUE)
                loadPreview()
                ;open tab 1
                setGadgetState(#PANEL1, 1)
                setActiveGadget(#WEB1)
                wdt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
                hgt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
                statusBarText(#STAT1, 0, " PREVIEW SIZE: :  " + str(wdt) + " / " + str(hgt), #PB_STATUSBAR_BORDERLESS) 
              else
                disableMenuItems(#MENU, #FILE_OPEN, #HELP_ABOUT, #FALSE)                
                setGadgetState(#PANEL1, 0)
                StatusBarText(#STAT1, 0, "  LINE NUMBER:  " + str(line),  #PB_STATUSBAR_BORDERLESS)
                statusBarText(#STAT1, 0, "  Licenced To: UNLICENCED") 
                setActiveGadget(#EDIT1)
              endIf
            case 1
              ;switch to html file
              disablemenuItems(#MENU, #FILE_OPEN, #HELP_ABOUT, #FALSE)
              ;unload the preview
              setGadgetText(#WEB1, "about:")
              ;open tab 0
              setGadgetState(#PANEL1, 0)
              setActiveGadget(#EDIT1)
          endSelect
          
;-\menu file
        case #FILE_OPEN
          fileOpen()
          setActiveGadget(#EDIT1)

        case #FILE_INSERT
          fileInsert()
          setActiveGadget(#EDIT1)

        case #FILE_NEW
          fileNew()
          setActiveGadget(#EDIT1)

        case #FILE_RECENT1
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent1
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT2
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent2
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT3
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent3
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT4
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent4
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT5
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent5
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT6
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent6
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT7
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent7
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_RECENT8
          if recent1 <> "[No file]"
            if saveModifiedFile() <> #IDCANCEL
              path.s = recent8
              reLoad(#EDIT1, path, 0)
              fileName = getFilePart(path)
              fileOpenFolder = getPathPart(path)
              setWindowTitle(#WIN1, appName + " - " + path)
            endIf
          endIf
          setActiveGadget(#EDIT1)

        case #FILE_INSERT
          fileInsert()
          setActiveGadget(#EDIT1)

        case #FILE_SAVE
          fileSave()
          setActiveGadget(#EDIT1)

        case #FILE_SAVEAS
          fileSaveAs()
          setActiveGadget(#EDIT1)

        case #FILE_SAVECOPY
          fileSaveCopy()
          setActiveGadget(#EDIT1)

        case #FILE_SAVETO
          fileSaveTo()
          setActiveGadget(#EDIT1)

        case #FILE_PRINT
          if fileSave()
            runProgram("notepad.exe", "/p " + fileOpenFolder + fileName, "")      
          endIf
          
        case #FILE_HOME
          fileHome()
          
        case #FILE_EXPLORE
          shellExecute_(0, "explore", fileOpenFolder, 0, 0, #SW_SHOWNORMAL)
          
        case #FILE_FIND
          shellExecute_(0, "find", fileOpenFolder, 0, 0, #SW_SHOWNORMAL)
          
        case #FILE_QUIT
         if saveModifiedFile() <> #IDCANCEL
            break
          endIf

;-\menu edit
        case #EDIT_UNDO
          sendMessage_(gadgetId(#EDIT1), #WM_UNDO, 0, 0)

        case #EDIT_SELECTALL
          sendMessage_(gadgetId(#EDIT1), #EM_SETSEL, 0, -1)

        case #EDIT_CUT
          sendMessage_(gadgetId(#EDIT1), #WM_CUT, 0, 0)

        case #EDIT_COPY
          sendMessage_(gadgetId(#EDIT1), #WM_COPY, 0, 0)

        case #EDIT_PASTE
          ;sendMessage_(gadgetId(#EDIT1), #WM_PASTE, 0, 0)
          sendMessage_(gadgetId(#EDIT1), #EM_PASTESPECIAL, #CF_TEXT, 0)
          
        case #EDIT_ERASE
          sendMessage_(GadgetID(#EDIT1), #WM_CLEAR, 0, 0)

        case #EDIT_FINDREPL
          findReplace(#EDIT1)
          
        case #EDIT_CONVERT
          flags = #MB_ICONWARNING | #MB_OKCANCEL
          msg.s = "This will converted the html code and place it on the clipboard." + #CRLF$
          msg + "The html code in the editor will not be affected." + #CRLF$ + #CRLF$
          msg + "Click OK to convert, or Cancel to quit."
          if messageRequester("Convert to string statements", msg, flags) = #IDOK
            convertTostring()
          endIf

;-\menu tools
        case #TOOLS_SEARCH1
          ;reset topmost if opening another program
          setMenuItemState(#MENU, #SETUP_TOPMOST, 0)
          stickyWindow(#WIN1, 0)
          ;get any selected text in the richedit
          sendMessage_(gadgetId(#EDIT1), #EM_EXGETSEL, 0, @text.FINDTEXT\chrg)
          if (text\chrg\cpMin <> text\chrg\cpMax)
            ;selected text range found, check it's length
            len = text\chrg\cpMax - text\chrg\cpMin
            if len < 128
              char.c
              *txt = allocateMemory((len + 1) * sizeOf(char))
              ;get the selected text
              sendMessage_(gadgetId(#EDIT1), #EM_GETSELTEXT, 0, *txt)
              ;open the site and search for the selected text
              runProgram("http://www.google.com/search?q=" + peekS(*txt) + "&btnG")
              freeMemory(*txt)
            endIf
          else
            ;no selected text, open the site
            runProgram("http://www.google.com")
          endIf

        case #TOOLS_SEARCH2
          ;reset topmost if opening another program
          setMenuItemState(#MENU, #SETUP_TOPMOST, 0)
          stickyWindow(#WIN1, 0)
          ;open site
          ;get any selected text in the richedit
          sendMessage_(gadgetId(#EDIT1), #EM_EXGETSEL, 0, @text.FINDTEXT\chrg)
          if (text\chrg\cpMin <> text\chrg\cpMax)
            ;selected text range found, check it's length
            len = text\chrg\cpMax - text\chrg\cpMin
            if len <= 128
              char.c
              *txt = allocateMemory((len + 1) * sizeOf(char))
              ;get the selected text
              sendMessage_(gadgetId(#EDIT1), #EM_GETSELTEXT, 0, *txt)
              ;open the site and search for the selected text
              runProgram("http://www.google.com/search?sitesearch=www.w3schools.com&as_q=" + peekS(*txt))
              freeMemory(*txt)
            endIf
          else
            ;no selected text, open the site
            runProgram("http://www.w3schools.com")
          endIf

        case #TOOLS_NOTEPAD
          ;reset topmost if opening another program
          setMenuItemState(#MENU, #SETUP_TOPMOST, 0)
          stickyWindow(#WIN1, 0)
          ;open notepad
          runProgram("notepad.exe")

        case #TOOLS_SYSMON
          ;reset topmost if opening another program
          setMenuItemState(#MENU, #SETUP_TOPMOST, 0)
          stickyWindow(#WIN1, 0)
          ;open system monitor
          runProgram("perfmon.exe")

        case #TOOLS_MAGNIFY
          runProgram("magnify.exe")
          
;-\menu setup
        case #SETUP_TOPMOST
          if getmenuItemState(#MENU, #SETUP_TOPMOST)
            setMenuItemState(#MENU, #SETUP_TOPMOST, 0)
            stickyWindow(#WIN1, 0)
          else
            setMenuItemState(#MENU, #SETUP_TOPMOST, 1)
            stickyWindow(#WIN1, 1)
          endIf

        case #SETUP_FONT
          setupFont()
          setActiveGadget(#EDIT1)

        case #SETUP_SIZ1
          setPreviewSize(800, 0)

        case #SETUP_SIZ2
          setPreviewSize(1024, 0)

        case #SETUP_SIZ3
          setPreviewSize(1280, 0)

        case #SETUP_WDT1
          setPreviewSize(GetSystemMetrics_(#SM_CXSCREEN) * 0.9, 0)

        case #SETUP_WDT2
          setPreviewSize(GetSystemMetrics_(#SM_CXSCREEN) * 0.5, 0)

        case #SETUP_WDT3
          setPreviewSize(GetSystemMetrics_(#SM_CXSCREEN) * 0.25, 0)

        case #SETUP_HGT1
          setPreviewSize(0, GetSystemMetrics_(#SM_CYSCREEN) * 0.8)

        case #SETUP_HGT2
          setPreviewSize(0, GetSystemMetrics_(#SM_CYSCREEN) * 0.5)

        case #SETUP_HGT3
          setPreviewSize(0, GetSystemMetrics_(#SM_CYSCREEN) * 0.25)

        case   #SETUP_COLOR
          color = colorRequester(rgb(216, 234, 255))
          If color <> -1  
            backColor = color
            setGadgetColor(#EDIT1, #PB_GADGET_BACKCOLOR, backColor)
          endIf
          setActiveGadget(#EDIT1)

        case #SETUP_DESKTOP
          ;create a shortcut to this program on the desktop
          res.s = programFileName()
          url.s = getSpecialFolder(#CSIDL_DESKTOPDIRECTORY) + appName
          if createShortcut(#TRUE, res, url, res, 0)
            messageRequester(appName, "Shortcut created", #MB_ICONINFORMATION)
          endIf
          setActiveGadget(#EDIT1)

        case #SETUP_STARTMENU
          ;create a shortcut to this program in the startmenu
          res.s = programFileName()
          url.s = getSpecialFolder(#CSIDL_PROGRAMS) + appName
          if createShortcut(#TRUE, res, url, res, 0)
            messageRequester(appName, "Shortcut created", #MB_ICONINFORMATION)
          endIf
          setActiveGadget(#EDIT1)
 
         case #HELP_HTM
          runProgram(appname + ".htm1.html")
          setActiveGadget(#EDIT1)

        case #HELP_PDF
          runProgram(appName + ".pdf1.pdf")
          setActiveGadget(#EDIT1)

        case #HELP_ABOUT
          helpAbout()
          setActiveGadget(#EDIT1)
      endSelect

;-\popup menu
    case #WM_RBUTTONDOWN
      select eventWindow()
        case #WIN1
          if getGadgetState(#PANEL1) = 0
            displayPopupmenu(#POP_UP, windowId(#WIN1))
          endIf
      endSelect

;-\resize
    case #PB_EVENT_SIZEWINDOW
      if getWindowState(#WIN1) = #PB_WINDOW_MAXIMIZE
        maximized = 1
      else
       maximized = 0
        windowW = windowWidth(#WIN1)
        windowH = windowHeight(#WIN1)
      endIf
      resizeGadget(#PANEL1, 0, 0, windowWidth(#WIN1), windowHeight(#WIN1) - menuHeight() - statusBarHeight(#STAT1))
      wdt = getgadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
      hgt = getgadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
      resizeGadget(#EDIT1, 0, 0, wdt, hgt)
      resizeGadget(#WEB1, 0, 0, wdt, hgt)
      select getGadgetState(#PANEL1)
        case 0
          setActiveGadget(#EDIT1)
        case 1
          setActiveGadget(#WEB1)
          statusBarText(#STAT1, 0, " PREVIEW SIZE:  " + str(wdt) + " X " + str(hgt)) 
      endSelect

    case #PB_EVENT_CLOSEWINDOW
      if saveModifiedFile() <> #IDCANCEL
        break
      endIf
  endSelect
forever

;-program exit
closeWindow(#WIN1)
writePreferences(inFolder, name)
end

;-
procedure openMainWindow()
  flags = #PB_WINDOW_SYSTEMMENU |  #PB_WINDOW_SIZEGADGET
  flags | #PB_WINDOW_MINIMIZEGADGET | #PB_WINDOW_MAXIMIZEGADGET
  text.s = appName + " - " + fileOpenFolder + fileName
  if openWindow(#WIN1, 0, 0, windowW, windowH, text, flags)
    setWindowColor(#WIN1, rgb(192, 224, 255))
    if maximized
      SetWindowState(#WIN1, #PB_WINDOW_MAXIMIZE)
    else
      ;center at top
      l = (GetSystemMetrics_(#SM_CXSCREEN) - windowWidth(#WIN1)) / 2
      resizeWindow(#WIN1, l, 0, #PB_IGNORE, #PB_IGNORE)
    endIf
;-\main menu
    hMnu = createmenu(#MENU, windowId(#WIN1))
    if hMnu
      menuTitle("&File")
      ;for the menu icons procedure
      hMnu0 = getSubMenu_(hMnu, 0)
      
      menuItem(#FILE_OPEN, "&Open..." + chr(9) + "Ctrl + O")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_O, #FILE_OPEN)      

      menuItem(#FILE_INSERT, "&Insert..." + chr(9) + "Ctrl + I")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_I, #FILE_INSERT)      

      menuItem(#FILE_NEW, "&New" + chr(9) + "Ctrl + N")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_N, #FILE_NEW)      

      openSubMenu("Recent Files...")
        menuItem(#FILE_RECENT1, recent1)
        menuItem(#FILE_RECENT2, recent2)
        menuItem(#FILE_RECENT3, recent3)
        menuItem(#FILE_RECENT4, recent4)
        menuItem(#FILE_RECENT5, recent5)
        menuItem(#FILE_RECENT6, recent6)
        menuItem(#FILE_RECENT7, recent7)
        menuItem(#FILE_RECENT8, recent8)
      closeSubMenu()
      menuBar()

      menuItem(#FILE_INSERT, "&Insert..." + chr(9) + "Ctrl + I")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_I, #FILE_INSERT)      
      menuBar()

      menuItem(#FILE_SAVE, "&Save" + chr(9) + "Ctrl + S")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_S, #FILE_SAVE)      

      menuItem(#FILE_SAVEAS, "Save As...")      
      menuItem(#FILE_SAVECOPY, "Save Copy As...")
      menuItem(#FILE_SAVETO, "Save To...")      
      menuBar()

      menuItem(#FILE_PRINT, "&Print" + chr(9) + "Ctrl + P")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_P, #FILE_PRINT)      
      menuBar()

      menuItem(#FILE_HOME, "User Home")
      menuItem(#FILE_EXPLORE, "&Explore" + chr(9) + "Ctrl + E")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_E, #FILE_EXPLORE)      
      menuItem(#FILE_FIND, "Find...")
      menuBar()

      menuItem(#FILE_QUIT, "&Quit" + chr(9) + "Ctrl + Q")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_Q, #FILE_QUIT)      

      ;edit menuitem
      menuTitle("&Edit")
      menuItem(#EDIT_UNDO, "Undo" + chr(9) + "Ctrl + Z")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_Z, #EDIT_UNDO)      
      menuBar()

      menuItem(#EDIT_CUT, "Cut" + chr(9) + "Ctrl + X")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_X, #EDIT_CUT)      

      menuItem(#EDIT_COPY, "&Copy" + chr(9) + "Ctrl + C")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_C, #EDIT_COPY)      

      menuItem(#EDIT_PASTE, "Paste" + chr(9) + "Ctrl + V")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_V, #EDIT_PASTE)      

      menuItem(#EDIT_ERASE, "&Erase" + chr(9) + "Ctrl + E")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_E, #EDIT_ERASE)      
      menuBar()

      menuItem(#EDIT_SELECTALL, "Select &All" + Chr(9) + "Ctrl + A")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_A, #EDIT_SELECTALL)          
      menuBar()

      menuItem(#EDIT_FINDREPL, "&Find/Replace..." + chr(9) + "Ctrl + F")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_F, #EDIT_FINDREPL)      
      menuBar()
      menuItem(#EDIT_CONVERT, "Convert to string statements")

      ;tools menuitem
      menuTitle("&Tools")
      menuItem(#TOOLS_SEARCH1, "&Google" + chr(9) + "Ctrl + G")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_G, #TOOLS_SEARCH1)      

      menuItem(#TOOLS_SEARCH2, "&W3schools" + chr(9) + "Ctrl + W")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_W, #TOOLS_SEARCH2)      
      menuBar()

      menuItem(#TOOLS_NOTEPAD, "Notepad")
      menuItem(#TOOLS_SYSMON, "System &Monitor" + chr(9) + "Ctrl + M")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_M, #TOOLS_SYSMON)      
      menuItem(#TOOLS_MAGNIFY, "Magnifier")

      ;setup menuitem
      menuTitle("&Setup")
      menuItem(#SETUP_TOPMOST, "Always On &Top" + chr(9) + "Ctrl + T")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_T, #SETUP_TOPMOST)      
      menuBar()

      menuItem(#SETUP_SIZ1, "Width 800px")
      menuItem(#SETUP_SIZ2, "Width 1024px")
      menuItem(#SETUP_SIZ3, "Width 1280px")
      menuBar()

      menuItem(#SETUP_WDT1, "Width 90%")
      menuItem(#SETUP_WDT2, "Width 50%")
      menuItem(#SETUP_WDT3, "Width 25%")
      menuBar()

      menuItem(#SETUP_HGT1, "Height 80%")
      menuItem(#SETUP_HGT2, "Height 50%")
      menuItem(#SETUP_HGT3, "Height 25%")
      menuBar()

      menuItem(#SETUP_FONT, "Editor Font/Font Color...")
      menuItem(#SETUP_COLOR, "Editor Background Color...")
      menuBar()

      menuItem(#SETUP_DESKTOP, "Create Desktop Shortcut")
      menuItem(#SETUP_STARTMENU, "Create Startmenu Shortcut")

      ;help menuitem
      menuTitle("&Help")
      if fileSize(appFolder + appName + ".htm1.html") <> -1
        ;a html help file exists, add a shortcut to it
        menuItem(#HELP_HTM, "&Help" + chr(9) + "Ctrl + H")
        addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_H, #HELP_HTM)      
      endIf
      if fileSize(appFolder + appName + ".pdf1.pdf") <> -1
        ;a manual file exists, add a shortcut to it
        menuItem(#HELP_PDF, "Manual")
      endIf
      menuItem(#HELP_ABOUT, "About " + appName)
    else
      ;error
      procedureReturn 0
    endIf

;-\popupmenu
    hMnu = createPopupmenu(#POP_UP)
    if hMnu
      ;edit main menu items
      menuItem(#FILE_OPEN, "&Open..." + chr(9) + "Ctrl + O")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_O, #FILE_OPEN)      
      menuBar()

      menuItem(#FILE_NEW, "&New" + chr(9) + "Ctrl + N")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_N, #FILE_NEW)      

      menuItem(#FILE_INSERT, "&Insert..." + chr(9) + "Ctrl + I")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_I, #FILE_INSERT)      
      menuBar()

      menuItem(#FILE_SAVE, "&Save" + chr(9) + "Ctrl + S")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_S, #FILE_SAVE)      

      menuItem(#FILE_SAVEAS, "Save As...")      

      menuItem(#FILE_SAVECOPY, "Save Copy As...")
      menuBar()

      menuItem(#EDIT_UNDO, "Undo" + chr(9) + "Ctrl + Z")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_Z, #EDIT_UNDO)      
      menuBar()

      menuItem(#EDIT_CUT, "Cut" + chr(9) + "Ctrl + X")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_X, #EDIT_CUT)      

      menuItem(#EDIT_COPY, "&Copy" + chr(9) + "Ctrl + C")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_C, #EDIT_COPY)      

      menuItem(#EDIT_PASTE, "Paste" + chr(9) + "Ctrl + V")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_V, #EDIT_PASTE)      

      menuItem(#EDIT_ERASE, "&Erase" + chr(9) + "Ctrl + E")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_E, #EDIT_ERASE)      
      menuBar()      

      menuItem(#EDIT_SELECTALL, "Select &All" + chr(9) + "Ctrl + A")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_A, #EDIT_SELECTALL)      

      menuItem(#EDIT_FINDREPL, "&Find/Replace..." + chr(9) + "Ctrl + F")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_F, #EDIT_FINDREPL)      
      menuBar()

      menuItem(#EDIT_CONVERT, "Convert to string statements")
      menuBar()

      menuItem(#FILE_PRINT, "&Print" + chr(9) + "Ctrl + P")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_P, #FILE_PRINT)      
      menuBar()

      menuItem(#FILE_EXPLORE, "&Explore" + chr(9) + "Ctrl + E")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_E, #FILE_EXPLORE)
      menuItem(#FILE_FIND, "Find...")
      menuBar()

      menuItem(#FILE_QUIT, "&Quit" + chr(9) + "Ctrl + Q")
      addKeyboardShortcut(#WIN1, #PB_SHORTCUT_CONTROL | #PB_SHORTCUT_Q, #FILE_QUIT)      
    else
      ;error
      procedureReturn 0
    endIf
    
    ;F5 shortcut to switch between tabs
    addKeyboardShortcut(#WIN1, #PB_SHORTCUT_F5, #PB_SHORTCUT_F5)

;-\statusbar
    if createStatusBar(#STAT1, windowId(#WIN1))
      addStatusBarField(400)
      statusBarText(#STAT1, 0, "  Licenced To: UNLICENCED") 
    endIf
        
;-\gadgets
      panelGadget(#PANEL1, 0, 0, windowWidth(#WIN1), windowHeight(#WIN1) - menuHeight() - statusBarHeight(#STAT1))

      ;tab 0, html file
      addGadgetItem(#PANEL1, 0, "Html Source File")
      wdt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
      hgt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
      editorGadget(#EDIT1, 0, 0, wdt, hgt)
      
      ;buffer editorgadget, for use with the convert function
      editorGadget(#BUFFER, 0, 0, 0, 0)

      ;set up the editorgadget to send caret notifications to get line number:
      evMask = sendMessage_(gadgetID(#EDIT1), #EM_GETEVENTMASK, 0, 0)
      sendMessage_(gadgetID(#EDIT1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS)
 
      ;remove the editorgadget border
      style = getWindowLong_(gadgetId(#EDIT1), #GWL_EXSTYLE)
      newstyle = style & (~#WS_EX_CLIENTEDGE)
      setWindowLong_(gadgetId(#EDIT1), #GWL_EXSTYLE, newstyle)
      setWindowPos_(gadgetId(#EDIT1), 0, 0, 0, 0, 0, #SWP_SHOWWINDOW|#SWP_NOSIZE|#SWP_NOMOVE|#SWP_FRAMECHANGED)
      
      ;editorgadget font
      hFont = loadFont(0, fontName, fontSize)
      setGadgetFont(#EDIT1, hFont)
      
      ;set text size limit (bytes) and colors
      sendMessage_(GadgetID(#EDIT1), #EM_EXLIMITTEXT, 0, 1024 * 1024 * 1024)
      setGadgetColor(#EDIT1, #PB_GADGET_FRONTCOLOR, fontColor)
      setGadgetColor(#EDIT1, #PB_GADGET_BACKCOLOR, backColor)

      ;set up margins to allow for linenumbers
      getClientRect_(gadgetId(#EDIT1), rc.RECT)
      rc\left = leftM
      sendMessage_(gadgetId(#EDIT1), #EM_SETRECT, 0, rc) 

      ;subclass the editorgadget to handle linenumbers
      editProc = setWindowLong_(gadgetID(#EDIT1), #GWL_WNDPROC, @editCallback()) 

      ;tab 1, html preview
      addGadgetItem(#PANEL1, 1, "Save/Page Preview")
      wdt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
      hgt = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
      webGadget(#WEB1, 0, 0, wdt, hgt, "about:")
      closeGadgetList()

      ;open tab 0
      setGadgetState(#PANEL1, 0)
      setActiveGadget(#EDIT1)
  endIf
    
  resetModified()
  procedureReturn
endProcedure

;-
procedure disableMenuItems(id, first, last, true)
  for item = first To last
    disableMenuItem(id, item, true)
  next item
endProcedure

;-
procedure fileNew()
  if saveModifiedFile() <> #IDCANCEL
    fileName = untitled
    setWindowTitle(#WIN1, appName + " - " + fileName)
  endIf
endProcedure

procedure fileHome()
  ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
  path.s = openFileRequester("", getHomeDirectory(), ext, 0)
  if path
    if saveModifiedFile() <> #IDCANCEL
      reLoad(#EDIT1, path, 0)
      fileName = getFilePart(path)
      fileOpenFolder = getPathPart(path)
      setWindowTitle(#WIN1, appName + " - " + path)
      setActiveGadget(#EDIT1)
    endIf
  endIf
endProcedure

procedure fileOpen()
  if saveModifiedFile() <> #IDCANCEL
    ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
    path.s = openFileRequester("Open File", fileOpenFolder, ext, 0)
    if path
      reLoad(#EDIT1, path, 0)
      fileName = getFilePart(path)
      fileOpenFolder = getPathPart(path)
      saveRecentFiles(fileOpenFolder + fileName)
      setWindowTitle(#WIN1, appName + " - " + path)
    endIf
  endIf
endProcedure

procedure saveRecentFiles(path.s)
  recent8 = getMenuItemText(#MENU, #FILE_RECENT7)
  setMenuItemText(#MENU, #FILE_RECENT8, recent8)
  
  recent7 = getMenuItemText(#MENU, #FILE_RECENT6)
  setMenuItemText(#MENU, #FILE_RECENT7, recent7)
  
  recent6 = getMenuItemText(#MENU, #FILE_RECENT5)
  setMenuItemText(#MENU, #FILE_RECENT6, recent6)
  
  recent5 = getMenuItemText(#MENU, #FILE_RECENT4)
  setMenuItemText(#MENU, #FILE_RECENT5, recent5)
  
  recent4 = getMenuItemText(#MENU, #FILE_RECENT3)
  setMenuItemText(#MENU, #FILE_RECENT4, recent4)
  
  recent3 = getMenuItemText(#MENU, #FILE_RECENT2)
  setMenuItemText(#MENU, #FILE_RECENT3, recent3)
  
  recent2 = getMenuItemText(#MENU, #FILE_RECENT1)
  setMenuItemText(#MENU, #FILE_RECENT2, recent2)
  
  recent1 = path
  setMenuItemText(#MENU, #FILE_RECENT1, recent1)
endProcedure

procedure fileInsert()
  ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
  path.s = openFileRequester("Insert File", fileInsertFolder, ext, 0)
  if path
    insertFile(#EDIT1, path)
    fileInsertFolder = getPathPart(path)
  endIf
endProcedure

procedure fileSave()
  if fileName = untitled
    if fileSaveAs() = #FALSE
      procedureReturn #FALSE
    endIf
  else
    reSave(#EDIT1, fileOpenFolder + fileName, 0)
  endIf
  procedureReturn #TRUE
endProcedure

procedure fileSaveAs()
  ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
  path.s = saveFileRequester("Save File As", fileOpenFolder + fileName, ext, 0)
  if path
    if getExtensionPart(path) = ""
        path + ".html"
    endIf
    reSave(#EDIT1, path, 0)
    fileName = getFilePart(path)
    fileOpenFolder = getPathPart(path)
    setWindowTitle(#WIN1, appName + " - " + path)
  else
    procedureReturn #FALSE
  endIf
  procedureReturn #TRUE  
endProcedure

procedure fileSaveCopy()
  ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
  path.s = saveFileRequester("Save Copy As", fileSaveCopyFolder + fileName, ext, 0)
  if path
    if getExtensionPart(path) = ""
        path + ".html"
    endIf
    reSave(#EDIT1, path, 0)
    fileSaveCopyFolder = getPathPart(path)
  else
    procedureReturn #FALSE
  endIf
  procedureReturn #TRUE  
endProcedure

procedure fileSaveTo()
  ext.s = "Html Source (*.htm *.html *.css *.txt)|*.htm;*.html;*.css;*.txt|All files (*.*)|*.*"
  path.s = saveFileRequester("Save to the end of file", fileSavetoFolder + fileName, ext, 0)
  if path
    if openFile(0, path)
      ;gote end of the file
      fileSeek(0, lof(0))
      ;write a newline
      writeString(0, "")
      for line = 0 to countGadgetItems(#EDIT1)
        writeStringN(0, GetGadgetItemText(#EDIT1, line, 0))
      next line
      closeFile(0)
      fileSavetoFolder = getPathPart(path)
    endIf
  else
    procedureReturn #FALSE
  endIf
  procedureReturn #TRUE  
endProcedure
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Re: Htm source editor with preview

Post by utopiomania »

Code: Select all

;-
procedure findReplace(id)
  flags = #PB_WINDOW_SYSTEMMENU | #PB_WINDOW_SCREENCENTERED
  win = openWindow(#PB_ANY, 0, 0, 400, 145, "Find/Replace", flags)
  if win
    stickyWindow(win, #TRUE)
      ;draw the find icon        
      img1 = createImage(#PB_ANY, 22, 22) 
      if startDrawing(imageOutput(img1)) 
        box(0, 0, 24, 24, getSysColor_(15))
        ;icon index 176, 55 
        extractIconEx_("shell32.dll", 176, 0, @icon, 1) 
        if icon 
          drawImage(icon, 0, 0, 21, 21) 
          destroyIcon_(icon) 
        endIf 
        stopDrawing() 
      endIf
      if 1
        imageGadget(#PB_ANY, 10, 15, 0, 0, imageId(img1))
        textGadget(#PB_ANY, 40, 20, 75, 22, "Find:")
      else
        textGadget(#PB_ANY, 10, 20, 75, 22, "Find What:")
      endIf
      str1 = stringGadget(#PB_ANY, 100, 15, 200, 21, "")
      textGadget(#PB_ANY, 10, 50, 75, 22, "Replace With:")
      str2 = stringGadget(#PB_ANY, 100, 45, 200, 21, "")
      btn1 = buttonGadget(#PB_ANY, 310, 15, 80, 22, "Find Next", #PB_BUTTON_DEFAULT)
      disableGadget(btn1, #TRUE)
      btn2 = buttonGadget(#PB_ANY, 310, 45, 80, 22, "Replace")
      disableGadget(btn2, #TRUE)
      btn3 = buttonGadget(#PB_ANY, 310, 80, 80, 22, "Replace all")
      disableGadget(btn3, #TRUE)
      btn4 = buttonGadget(#PB_ANY, 310, 110, 80, 22, "Cancel")

      chk1 = checkBoxGadget(#PB_ANY, 10, 80, 120, 22, "Match Case")
      chk2 = checkBoxGadget(#PB_ANY, 10, 112, 120, 22, "Whole Words only")
      chk3 = checkBoxGadget(#PB_ANY, 140, 112, 160, 22, "Search From Top")
      
      ;get any selected text in the richedit
      sendMessage_(gadgetId(id), #EM_EXGETSEL, 0, @text.FINDTEXT\chrg)
      if (text\chrg\cpMin <> text\chrg\cpMax)
        ;selected text range found, check it's length
        len = text\chrg\cpMax - text\chrg\cpMin
        if len < 128
          debug len
          char.c
          *txt = allocateMemory((len + 1) * sizeOf(char))
          ;get the selected text
          sendMessage_(gadgetId(id), #EM_GETSELTEXT, 0, *txt)
          setGadgettext(str1, peekS(*txt))
          freeMemory(*txt)
          ;focus the replace input field
          setActiveGadget(str2)
          ;enable the buttons
          disableGadget(btn1, #FALSE)
          disableGadget(btn2, #FALSE)
          disableGadget(btn3, #FALSE)
        endIf
      else
        ;focus the findstring input field
        setActiveGadget(str1)
      endIf
            
      ;no text found yet:
      pos = -1
      ;default search flag
      flg | #FR_DOWN

      repeat
        event = waitWindowEvent()
        if eventWindow() = win
          select event
            case #PB_EVENT_GADGET
              select eventGadget()
                case str1
                  ;find string
                  gadgetTooltip(str1, getGadgettext(str1))
                  if len(getGadgettext(str1))
                    disableGadget(btn1, #FALSE)
                    disableGadget(btn2, #FALSE)
                    disableGadget(btn3, #FALSE)
                  else
                    disableGadget(btn1, #TRUE)
                    disableGadget(btn2, #TRUE)
                    disableGadget(btn3, #TRUE)
                  endIf
                  
                case str2
                  ;replace string
                  gadgetTooltip(str2, getGadgettext(str2))

                case btn1
                  ;find button
                  find.s = getGadgettext(str1)
                  text.FINDTEXT\lpstrText = @find
                  ;get current position or selected range in the text
                  sendMessage_(gadgetId(id), #EM_EXGETSEL, 0, @text\chrg)
                  if (text\chrg\cpMin <> text\chrg\cpMax)
                    ;selected text range found, search from the end of it
                    text\chrg\cpMin = text\chrg\cpMax
                  endIf
                  if getGadgetState(chk3)
                    ;reset, search from the top
                    setGadgetState(chk3, 0)
                    text\chrg\cpMin = 0
                  endIf 
                  ;search to the end of the text: 
                  text\chrg\cpMax = -1 
                  ;set the search flags
                  flg = 0
                  flg | #FR_DOWN
                  if getGadgetState(chk1)
                    flg | #FR_MATCHCASE
                  endIf
                  if getGadgetState(chk2)
                    flg | #FR_WHOLEWORD
                  endIf
                  pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text) 
                  if pos <> -1
                    ;found, select the text range
                    sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                  else
                    msg.s = "Cannot find " + find + chr(13) + chr(10)
                    msg + "Search again from the top ?"
                    flags = #MB_ICONQUESTION | #MB_YESNOCANCEL
                    select messageRequester("Find/Replace", msg, flags)
                      case #IDYES
                        ;first position in the text
                        sendMessage_(gadgetId(id), #EM_SETSEL, 0, 0)
                        text\chrg\cpMin = 0
                        ;search to the end of the text: 
                        text\chrg\cpMax = -1 
                        pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text)
                        if pos <> -1
                          ;found, select the text range
                          sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                        else
                          msg.s = "Cannot find " + find
                          flags = #MB_ICONINFORMATION | #MB_OKCANCEL
                          select messageRequester("Find/Replace", msg, flags)
                            case #IDCANCEL
                              break
                          endSelect
                        endIf 
                        setActiveGadget(id)
                      case #IDCANCEL
                        break
                    endSelect
                  endIf

                case btn2
                  ;replace button
                  ;get selected range in the text
                  sendMessage_(gadgetId(id), #EM_EXGETSEL, 0, @text\chrg)
                  if (text\chrg\cpMin <> text\chrg\cpMax)
                    ;found selected text range
                    repl.s = getGadgettext(str2)
                    if text\chrg\cpMax - text\chrg\cpMin = len(getGadgettext(str1))
                      ;same length as the find string, replace it
                      sendMessage_(gadgetId(id), #EM_REPLACESEL, 1, @repl)
                      ;advance the current position
                      text\chrg\cpMin + len(repl)
                    endIf
                  else
                    ;no selection made yet, search from the current position
                    text\chrg\cpMin = text\chrg\cpMax
                  endIf
                  if getGadgetState(chk3)
                    ;reset, search from the top
                    setGadgetState(chk3, 0)
                    text\chrg\cpMin = 0
                  endIf 
                  ;search to the end of the text: 
                  text\chrg\cpMax = -1
                  find.s = getGadgettext(str1)
                  text\lpstrText = @find
                  ;set the search flags
                  flg = 0
                  flg | #FR_DOWN
                  if getGadgetState(chk1)
                    flg | #FR_MATCHCASE
                  endIf
                  if getGadgetState(chk2)
                    flg | #FR_WHOLEWORD
                  endIf
                  pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text) 
                  if pos <> -1
                    ;found, select the text range
                    sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                  else
                    msg.s = "Cannot find " + find + chr(13) + chr(10)
                    msg + "Search again from the top ?"
                    flags = #MB_ICONQUESTION | #MB_YESNOCANCEL
                    select messageRequester("Find/Replace", msg, flags)
                      case #IDYES
                        ;first position in the text
                        sendMessage_(gadgetId(id), #EM_SETSEL, 0, 0)
                        text\chrg\cpMin = 0
                        ;search to the end of the text: 
                        text\chrg\cpMax = -1 
                        pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text)
                        if pos <> -1
                          ;found, select the text range
                          sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                        else
                          msg.s = "Cannot find " + find
                          flags = #MB_ICONINFORMATION | #MB_OKCANCEL
                          select messageRequester("Find/Replace", msg, flags)
                            case #IDCANCEL
                              break
                          endSelect
                        endIf 
                      case #IDCANCEL
                        break
                    endSelect
                  endIf

                case btn3
                  ;replace all button
                  repeat
                    ;get selected range in the text
                    sendMessage_(gadgetId(id), #EM_EXGETSEL, 0, @text\chrg)
                    if (text\chrg\cpMin <> text\chrg\cpMax)
                      ;found selected text range
                      repl.s = getGadgettext(str2)
                      if text\chrg\cpMax - text\chrg\cpMin = len(getGadgettext(str1))
                        ;same length as the find string, replace it
                        sendMessage_(gadgetId(id), #EM_REPLACESEL, 1, @repl)
                        ;advance the current position
                        text\chrg\cpMin + len(repl)
                      endIf
                    else
                      ;no selection made yet, search from the current position
                      text\chrg\cpMin = text\chrg\cpMax
                    endIf
                    if getGadgetState(chk3)
                      ;reset, search from the top
                      setGadgetState(chk3, 0)
                      text\chrg\cpMin = 0
                    endIf 
                    ;search to the end of the text: 
                    text\chrg\cpMax = -1
                    find.s = getGadgettext(str1)
                    text\lpstrText = @find
                    ;set the search flags
                    flg = 0
                    flg | #FR_DOWN
                    if getGadgetState(chk1)
                      flg | #FR_MATCHCASE
                    endIf
                    if getGadgetState(chk2)
                      flg | #FR_WHOLEWORD
                    endIf
                    pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text) 
                    if pos <> -1
                      ;found, select the text range
                      sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                    endIf
                  until pos = -1
            
                  msg.s = "Cannot find " + find + chr(13) + chr(10)
                  msg + "Search again from the top ?"
                  flags = #MB_ICONQUESTION | #MB_YESNOCANCEL
                  select messageRequester("Find/Replace", msg, flags)
                    case #IDYES
                      ;first position in the text
                      sendMessage_(gadgetId(id), #EM_SETSEL, 0, 0)
                      text\chrg\cpMin = 0
                      ;search to the end of the text: 
                      text\chrg\cpMax = -1 
                      pos = sendMessage_(gadgetId(id), #EM_FINDTEXT, flg, @text)
                      if pos <> -1
                        ;found, select the text range
                        sendMessage_(gadgetId(id), #EM_SETSEL, pos, pos + len(find))
                      else
                        msg.s = "Cannot find " + find
                        flags = #MB_ICONINFORMATION | #MB_OKCANCEL
                        select messageRequester("Find/Replace", msg, flags)
                          case #IDCANCEL
                            break
                        endSelect
                    endIf 
                    case #IDCANCEL
                      break
                  endSelect

                case btn4
                  ;cancel button
                  break
              endSelect
            case #PB_EVENT_CLOSEWINDOW
              break
          endSelect
        endIf
      forever
    closeWindow(win)
  endIf
endprocedure

;-
procedure setupFont()
  if fontRequester(fontName, fontSize, #PB_FontRequester_Effects)
    fontName = selectedFontName()
    fontSize = selectedFontSize()
    fontColor = selectedFontColor()
    setGadgetColor(#EDIT1, #PB_Gadget_FrontColor, fontColor)
    loadFont(0, fontName, fontSize, #PB_Font_HighQuality)
    setGadgetFont(#EDIT1, fontId(0))
    setGadgetFont(#EDIT1, fontId(0))
  endIf
endProcedure

;-
procedure helpAbout()
  ;text field1 
  txt.s = "About" + #TAB$ 
  ;text field2
  txt + "Html Editor" + #TAB$ 
  ;text field3
  txt + "www.utopiomania.com" + #TAB$ 
  ;text field4
  txt + "Copyright (C) 2008 stig henning johansen/utopiomania" + #TAB$ 
  ;text field5
  txt + "WARNING: This program is protected by copyright law and international treaties."+ #TAB$ 

  ;about html
	s.s + "<html>" + #CR$
	s + "<head>" + #CR$
	s + "<style type=" + #DQUOTE$ + "text/css" + #DQUOTE$ + ">" + #CR$
	s + "	body {margin:0; padding:0; position:absolute; overflow:hidden; background:#FFF; left:0; top:0; width:100%; height:100%;" + #CR$
	s + "		font-size: 12px;" + #CR$
	s + "		font-family: calibri;" + #CR$
	s + "		font-weight: normal;" + #CR$
	s + "	}" + #CR$
	s + "	.word {" + #CR$
	s + "		cursor: pointer;" + #CR$
	s + "		color: #000;" + #CR$
	s + "		position: absolute;" + #CR$
	s + "		z-index: 1;" + #CR$
	s + "	}" + #CR$
	s + "	.word_over {" + #CR$
	s + "		cursor: pointer;" + #CR$
	s + "		color: #FFF;" + #CR$
	s + "		position: absolute;" + #CR$
	s + "		z-index: 1;" + #CR$
	s + "	}" + #CR$
	s + "	.word_zoom {" + #CR$
	s + "		position: absolute;" + #CR$
	s + "		font-weight: bold;" + #CR$
	s + "		z-index: 0;" + #CR$
	s + "	}" + #CR$
	s + "</style>" + #CR$
	s + "" + #CR$
	s + "<script type=" + #DQUOTE$ + "text/javascript" + #DQUOTE$ + "><!--" + #CR$
	s + "window.onerror         = new Function(" + #DQUOTE$ + "return true" + #DQUOTE$ + ");" + #CR$
	s + "document.onselectstart = new Function(" + #DQUOTE$ + "return false" + #DQUOTE$ + ");" + #CR$
	s + "" + #CR$
	s + "var object = new Array();" + #CR$
	s + "var margin = 20;" + #CR$
	s + "var K = 0;" + #CR$
	s + "" + #CR$
	s + "function CObj(N,x,y,txt){" + #CR$
	s + "	this.obj = document.createElement(" + #DQUOTE$ + "span" + #DQUOTE$ + ");" + #CR$
	s + "	this.obj.innerHTML = txt;" + #CR$
	s + "	this.obj.className = " + #DQUOTE$ + "word" + #DQUOTE$ + ";" + #CR$
	s + "	this.obj.onmouseover = new Function(" + #DQUOTE$ + "this.className='word_over',object[" + #DQUOTE$ + "+N+" + #DQUOTE$ + "].izoom();" + #DQUOTE$ + ");" + #CR$
	s + "	document.getElementById(" + #DQUOTE$ + "sp" + #DQUOTE$ + ").appendChild(this.obj);" + #CR$
	s + "	this.obj.style.left = x;" + #CR$
	s + "	this.obj.style.top  = y;" + #CR$
	s + "	this.obz = 0;" + #CR$
	s + "	this.x  = x;" + #CR$
	s + "	this.y  = y;" + #CR$
	s + "	this.x0 = x;" + #CR$
	s + "	this.y0 = y;" + #CR$
	s + "	this.fs = 12;" + #CR$
	s + "	this.c  = 0;" + #CR$
	s + "	this.px = txt.length * .02;" + #CR$
	s + "	this.py = .04;" + #CR$
	s + "	this.zoom = function () {" + #CR$
	s + "		with(this){" + #CR$
	s + "			fs *= 1.08;" + #CR$
	s + "			c = 512 - fs * 2;" + #CR$
	s + "			x -= fs * px;" + #CR$
	s + "			y -= fs * py;" + #CR$
	s + "" + #CR$
	s + "			with(obz.style){" + #CR$
	s + "				left = x;" + #CR$
	s + "				top  = y;" + #CR$
	s + "				fontSize = Math.round(fs);" + #CR$
	s + "				color = " + #DQUOTE$ + "RGB(" + #DQUOTE$ + "+Math.round(c*.5)+" + #DQUOTE$ + "," + #DQUOTE$ + "+Math.round(c*.5)+" + #DQUOTE$ + "," + #DQUOTE$ + "+Math.round(c)+" + #DQUOTE$ + ")" + #DQUOTE$ + ";" + #CR$
	s + "			}" + #CR$
	s + "" + #CR$
	s + "			if(c<8){" + #CR$
	s + "				document.getElementById(" + #DQUOTE$ + "sp" + #DQUOTE$ + ").removeChild(obz);" + #CR$
	s + "				obj.className=" + #DQUOTE$ + "word" + #DQUOTE$ + ";" + #CR$
	s + "				x = x0;" + #CR$
	s + "				y = y0;" + #CR$
	s + "				fs = 12;" + #CR$
	s + "				obz = 0;" + #CR$
	s + "				K--;" + #CR$
	s + "			} else setTimeout(" + #DQUOTE$ + "object[" + #DQUOTE$ + "+N+" + #DQUOTE$ + "].zoom();" + #DQUOTE$ + ",16);" + #CR$
	s + "		}" + #CR$
	s + "	}" + #CR$
	s + "	this.izoom = function () {" + #CR$
	s + "		with(this){" + #CR$
	s + "			if(K<20){" + #CR$
	s + "				if(obz == 0){" + #CR$
	s + "					obz = document.createElement(" + #DQUOTE$ + "span" + #DQUOTE$ + ");" + #CR$
	s + "					obz.className = " + #DQUOTE$ + "word_zoom" + #DQUOTE$ + ";" + #CR$
	s + "					obz.innerHTML = txt;" + #CR$
	s + "					obz.style.left = x-1;" + #CR$
	s + "					obz.style.top  = y;" + #CR$
	s + "					document.getElementById(" + #DQUOTE$ + "sp" + #DQUOTE$ + ").appendChild(obz);" + #CR$
	s + "					zoom();" + #CR$
	s + "					K++;" + #CR$
	s + "				}" + #CR$
	s + "			} else setTimeout(" + #DQUOTE$ + "object[" + #DQUOTE$ + "+N+" + #DQUOTE$ + "].izoom();" + #DQUOTE$ + ",128);" + #CR$
	s + "		}" + #CR$
	s + "	}" + #CR$
	s + "}" + #CR$
	s + "" + #CR$
	s + "" + #CR$
	s + "function fontWidth(word){" + #CR$
	s + "	// arial font" + #CR$
	s + "	var S = " + #DQUOTE$ + "a68b68c68d68e68f31g68h68i31j31k68l31m108n68o68p68q68r39s68t39u68v50w90x68y68z68A90B90C90D90E90F78G98H90I28J59K90L68M108N90O98P90Q98R90S90T68U90V90W130X68Y90Z68'30.42!29?68-41/41=72" + #DQUOTE$ + ";" + #CR$
	s + "	var l = word.length;" + #CR$
	s + "	var s = 0;" + #CR$
	s + "	var x = 0;" + #CR$
	s + "	var c = 0;" + #CR$
	s + "	for(i=0;i<l;i++){" + #CR$
	s + "		c = word.charAt(i);" + #CR$
	s + "		x = S.indexOf(c);" + #CR$
	s + "		if(c>=" + #DQUOTE$ + "0" + #DQUOTE$ + " && c<=" + #DQUOTE$ + "9" + #DQUOTE$ + ")s+=69;" + #CR$
	s + "		else if(x>=0)s+=parseInt(S.substring(x+1,x+4));" + #CR$
	s + "		else s+=68;" + #CR$
	s + "	}" + #CR$
	s + "	return s/10;" + #CR$
	s + "}" + #CR$
	s + "" + #CR$
	s + "onload = function(){" + #CR$
	s + "" + #CR$
	s + "	T = [" + #CR$
	s + "		" + #DQUOTE$ + "Html Editor 20080105. Added Convert to string" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "statements that can be pasted and" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "loaded into the webgadget with the setItemtext()" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "procedure. The converted text is placed on the" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "clipboard directly, the text in the editor is" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "not affected. The program has a new Snapshot" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "functions that saves a snapshot of the text to" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "a temp file to make it possibløe to rollback if" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "anything goes haywire. This was added because" + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "the current file is saved on each preview." + #DQUOTE$ + "," + #CR$
	s + "		" + #DQUOTE$ + "Script:Gerard Ferrandez, www.dhteumeuleu.com" + #DQUOTE$ + "" + #CR$
	s + "		];" + #CR$
	s + "" + #CR$
	s + "	x = 0;" + #CR$
	s + "	y = 0;" + #CR$
	s + "	k = 0;" + #CR$
	s + "	for(j in T){" + #CR$
	s + "		Tx = T[j].split(" + #DQUOTE$ + " " + #DQUOTE$ + ");" + #CR$
	s + "		// justify" + #CR$
	s + "		xt = 0;" + #CR$
	s + "		for(i in Tx){" + #CR$
	s + "			txt = Tx[i];" + #CR$
	s + "			xt += fontWidth(txt);" + #CR$
	s + "		}" + #CR$
	s + "		if(Tx.length)sP = (-2*margin + parseInt(document.getElementById(" + #DQUOTE$ + "sp" + #DQUOTE$ + ").style.width) - xt) / (Tx.length-1); else sP = 0;" + #CR$
	s + "		// insert word" + #CR$
	s + "		for(i in Tx){" + #CR$
	s + "			txt = Tx[i];" + #CR$
	s + "			if(txt) {" + #CR$
	s + "				object[k] = new CObj(k, margin+x, margin+y, txt);" + #CR$
	s + "				x += (fontWidth(txt)+sP);" + #CR$
	s + "				k++;" + #CR$
	s + "			}" + #CR$
	s + "		}" + #CR$
	s + "		y += 18;" + #CR$
	s + "		x = 0;" + #CR$
	s + "	}" + #CR$
	s + "}" + #CR$
	s + "//-->" + #CR$
	s + "</script>" + #CR$
	s + "</head>" + #CR$
	s + "<body>" + #CR$
	s + "" + #CR$
	s + "<div style=" + #DQUOTE$ + "position:absolute;left:50%;top:50%" + #DQUOTE$ + ">" + #CR$
	s + "	<div id=" + #DQUOTE$ + "sp" + #DQUOTE$ + " style=" + #DQUOTE$ + "position:absolute;width:300;height:240;left:-150;top:-120;overflow:hidden;background:#FFF;cursor:pointer" + #DQUOTE$ + ">" + #CR$
	s + "	</div>" + #CR$
	s + "</div>" + #CR$
	s + "" + #CR$
	s + "</body></html>" + #CR$
	s + "" + #CR$
	s + "" + #CR$
	s + "" + #CR$
	s + "" + #CR$
	s + "" + #CR$
about(0, txt, s)
endProcedure

procedure about(parent, text.s, html.s)
  ;fields 
  about.s = stringField(text, 1, #TAB$) 
  name.s = stringField(text, 2, #TAB$) 
  corp.s = stringField(text, 3, #TAB$) 
  txt1.s = stringField(text, 4, #TAB$) 
  txt2.s = stringField(text, 5, #TAB$)
  link.s = stringField(text, 6, #TAB$)  
  http.s = stringField(text, 7, #TAB$)  

  flags = #PB_WINDOW_SCREENCENTERED  | #PB_WINDOW_SYSTEMMENU
  win = openWindow(#PB_ANY, 0, 0, 512, 400,  name, flags)
  if win 
    enableWindow_(windowId(parent), #FALSE)
    resizeWindow(win, #PB_IGNORE, windowY(win) - 50, #PB_IGNORE, #PB_IGNORE)
    stickyWindow(win, #TRUE) 

      ;graphics image gadget
      img1 = createImage(#PB_ANY, 512, 50)
      fnt1 = loadFont(#PB_ANY, "", 10) 
      fnt2 = loadFont(#PB_ANY, "", 16) 
      if startDrawing(imageOutput(img1))
        drawingMode(#PB_2DDRAWING_TRANSPARENT) 

        ;header background gradient 
        for x = 0 to 511 
          linexy(x, 0, x, 45, rgb(x / 2.5, x / 2.5, 255)) 
          linexy(x, 45, x, 50, rgb(225- x / 5, 225 - x / 5, 255)) 
        next x 

        res.s = "shell32.dll" 
        ndx = 130 
        ;res.s = programFileName() 
        ;ndx = 0 
        extractIconEx_(res, ndx, 0, @icon, 1) 
        if icon 
          drawImage(icon, 10, 5, 36, 36) 
          destroyIcon_(icon) 
        endIf 

        ;header about field 
        if fnt1 
          drawingFont(fontId(fnt1)) 
        endIf 
        drawText(60, 4, about, rgb(255, 255, 255)) 

        ;header program name field 
        if fnt2 
          drawingFont(fontId(fnt2)) 
        endIf 
        drawText(60, 18, name, rgb(255, 255, 255)) 

        ;header company name field 
        if fnt1 
          drawingFont(fontId(fnt1)) 
        endIf 
        drawText(500 - textWidth(corp), 25, corp, rgb(255, 255, 255)) 
        stopDrawing()
      endIf
      imageGadget(#PB_ANY, 0, 0, 512, 75, imageId(img1))
      
      ;upper text
      textGadget(#PB_ANY, 10, 66, 492, 35, txt1)
      
      ;about html
      web1 = webGadget(#PB_ANY, 10, 100, 490, 200, "")
      setGadgetItemText(web1, #PB_WEB_HTMLCODE, html)
      ;draw a frame aroud the webgadget
      frame3DGadget(#PB_ANY, 9, 99, 492, 202, "", #PB_FRAME3D_SINGLE)
      
      ;lower text
      textGadget(#PB_ANY, 10, 315, 492, 25, txt2)

      ;divider line
      frame3DGadget(#PB_ANY, 0, 340, 512, 2, "", #PB_FRAME3D_SINGLE)
      
      ;link/url 
      if len(link) 
        lnk1 = hyperLinkGadget(#PB_ANY, 20, 360, 200, 24, link, rgb(0, 0, 255), #PB_HYPERLINK_UNDERLINE) 
        SetGadgetColor(lnk1, #PB_GADGET_FRONTCOLOR, rgb(0, 0, 255)) 
      endIf 

      ;ok button
      btn1 = buttonGadget(#PB_ANY, 422, 360, 80, 24, "Ok", #PB_BUTTON_DEFAULT)
      addKeyboardShortcut(win, #PB_SHORTCUT_RETURN, btn1)
    
    repeat 
      event = waitWindowEvent() 
      select event 
        case #PB_EVENT_GADGET
          select eventGadget() 
            case lnk1 
              runProgram(http) 
              exit = #TRUE 
            case btn1 
              exit = #TRUE 
          endSelect 
        case #PB_EVENT_CLOSEWINDOW 
          exit = #TRUE 
      endSelect 
    until exit 
    closeWindow(win) 
  endIf 
  enableWindow_(windowId(parent), #TRUE) 
  setActiveWindow(parent)
endProcedure

;-
procedure reLoad(id, name.s, rtf)
  ;richedit streamin
  lenF = fileSize(name)
  if lenF
    fileH = readFile(#PB_Any, name)
    if lenF and fileH
      stream.EDITSTREAM
      stream\dwCookie = lenF
      stream\pfnCallback = @reLoadSaveCallback()
      if rtf
        ;rich text format
        SendMessage_(gadgetId(id), #EM_STREAMIN, #SF_RTF, @stream)
      else
        ;text format
        sendMessage_(gadgetId(id), #EM_STREAMIN, #SF_TEXT, @stream)
      endIf
      closeFile(fileH)
      resetModified()
      ;go to top of document
      sendMessage_(gadgetId(id), #EM_SETSEL, 0, 0)
    endIf
  endIf
endProcedure

procedure reSave(id, name.s, rtf)
  ;richedit streamout
  fileH = createFile(#PB_ANY, name)
  if fileH
    stream.EDITSTREAM
    stream\dwCookie = 0
    stream\pfnCallback = @reLoadSaveCallback()
    if rtf
      ;rich text format
      sendmessage_(gadgetId(id), #EM_STREAMOUT, #SF_RTF, @stream)
    else
      ;text format
      sendMessage_(gadgetid(id), #EM_STREAMOUT, #SF_TEXT, @stream)
    endIf
    closeFile(fileH)
    resetModified()
  endIf
endProcedure

procedure reLoadSaveCallback(lenF, *pbBuff, cb, *pcb.LONG)
  ;stream io callback
  if lenF = 0
    ;save
    writeData(fileH, *pbBuff, cb)
    *pcb\l = cb
  else
    ;load
    if lenF > cb
      *pcb\l = readData(fileH, *pbBuff, cb)
    else
      *pcb\l = readData(fileH, *pbBuff, lenF)
    endIf
  endIf
  procedureReturn 0
endProcedure

procedure editCallback(hWnd, uMsg, wParam, lParam) 
  select uMsg 
    case #WM_PAINT 
      callWindowProc_(editProc, hWnd, uMsg, wParam, lParam) 
      drawLineNumbers() 
      procedurereturn 0 
  endSelect 
  procedureReturn callWindowProc_(editProc, hWnd, uMsg, wParam, lParam) 
endProcedure

procedure drawLinenumbers()
  id = gadgetId(#EDIT1)
  hdc = GetDCEx_(id, 0, #DCX_CACHE)
 
;  hFont = fontId(getGadgetFont(#EDIT1))
  hFont = getGadgetFont(#EDIT1)

  prevObj = selectObject_(hDC, hFont) 

  getTextMetrics_(hDC, @tm.TEXTMETRIC) 
  fontH = tm\tmHeight
  
  getClientRect_(id, rc.RECT) 
  rc\right = leftM - 8
  fillRect_(hDC, rc, getStockObject_(#WHITE_BRUSH))
  setBkMode_(hDC, #TRANSPARENT)
  setTextColor_(hDC, $C0C0C0) 

  ;get the first line 
  first = SendMessage_(id, #EM_GETFIRSTVISIBLELINE, 0, 0) 

  ;get the last character/line  
  pt.POINT\x = rc\left 
  pt\y = rc\bottom 
  lastChar = sendMessage_(id, #EM_CHARFROMPOS, 0, pt) 
  last = sendMessage_(id, #EM_LINEFROMCHAR, lastChar, 0) 
  ; get the first character
  pt\y = rc\top
  firstChar = sendMessage_(id, #EM_CHARFROMPOS, 0, pt) 

  ;get the client coordinates fo the first character 
  sendMessage_(id, #EM_POSFROMCHAR, @tChar.POINT, firstChar) 
  ;adjust linenumber RECT 
  rc\top = tChar\y

  for line = first to last
    drawText_(hDc, str(line + 1), -1, rc, #DT_RIGHT) 
    rc\top + fontH
  next
  selectObject_(hDC, prevObj) 
  releaseDC_(id, hDC)
endProcedure

;-
procedure insertFile(id, path.s)
  if readFile(0, path)
    line = getLinenumber(id)
    while eof(0) = 0
      addGadgetItem(id, line, readString(0))
      line + 1
    wend
    closeFile(0)
  else
    procedurereturn #FALSE
  endIf
  procedurereturn #TRUE
endProcedure

procedure convertToString()
  ;copy current text into the buffer editorgadget
  sendMessage_(gadgetId(#EDIT1), #EM_SETSEL, 0, -1)
  sendMessage_(gadgetId(#EDIT1), #WM_COPY, 0, 0)
  sendMessage_(gadgetId(#BUFFER), #EM_PASTESPECIAL, #CF_TEXT, 0)

  ;converts the text to PureBasic string statements
  lines = countGadgetItems(#BUFFER)
  for line = 0 to lines - 1
    text.s = getGadgetItemText(#BUFFER, line)
    ;handle embedded dquotes
;    text = replaceString(text, #DQUOTE$, #DQUOTE$ + " + #DQUOTE$ + " + #DQUOTE$)
    text = replaceString(text, #DQUOTE$, #DQUOTE$ + " + chr(34) + " + #DQUOTE$)
    ;add dquotes and cr
    if line = 0
;      text = chr(9) + "s.s + " + #DQUOTE$ + text + #DQUOTE$ + " + #CR$"
      text = chr(9) + "s.s + " + #DQUOTE$ + text + #DQUOTE$ + " + chr(13)"
    else
;      text = chr(9) + "s + " + #DQUOTE$ + text + #DQUOTE$ + " + #CR$"
      text = chr(9) + "s + " + #DQUOTE$ + text + #DQUOTE$ + " + chr(13)"
    ;put it back
    setGAdgetItemText(#BUFFER, line, text)
    endif
  next line
  ;copy converted text back to the clipboard
  sendMessage_(gadgetId(#BUFFER), #EM_SETSEL, 0, -1)
  sendMessage_(gadgetId(#BUFFER), #WM_CUT, 0, 0)
  sendMessage_(gadgetId(#EDIT1), #EM_SETSEL, 0, -1)

  ;remove the selection
  sendMessage_(gadgetId(#EDIT1), #EM_SETSEL, 0, 0)
endProcedure

procedure saveModifiedFile()
  if isModified()
    select messageRequester("Save modified file?", fileName, #MB_YESNOCANCEL | #MB_ICONQUESTION)
      case #IDYES
        if fileSave() = #FALSE
          procedureReturn #IDCANCEL
        endIf
      case #IDCANCEL
        procedureReturn #IDCANCEL
    endSelect
  endIf
  procedurereturn #TRUE
endProcedure

procedure isModified()
  ;query the editorgadget for modified text since last reset
  result = sendMessage_(gadgetId(#EDIT1), #EM_GETMODIFY, 0, 0)
  procedureReturn result
endProcedure

procedure resetModified()
  ;reset editorgadget modify flag
  sendMessage_(gadgetId(#EDIT1), #EM_SETMODIFY, #FALSE, 0)
endProcedure

;-
procedure savePreview()
  if countGadgetItems(#EDIT1)
    if fileName = untitled
      if fileSave()
        procedureReturn #TRUE
      else
        procedureReturn #FALSE
      endIf
    else
      if lcase(getExtensionPart(fileName)) <> "css"
        reSave(#EDIT1, fileOpenFolder + fileName, 0)
      endIf
    endIf
    procedureReturn #TRUE
  endIf
  procedureReturn #FALSE
endProcedure

procedure loadPreview()
  if lcase(getExtensionPart(fileName)) <> "css"
    setGadgetText(#WEB1, "file://" + fileOpenFolder + fileName)
  else
    setGadgetText(#WEB1, "about:" + appName + " -  No preview available")
  endIf
endProcedure

;-
procedure processCmdLine()
  ;process command line parameters
  if countProgramParameters()
    ;open a doubleclicked file
    path.s = programParameter()
    reLoad(#EDIT1, path, 0)
    ;process dot commands:
    fileName = getFilePart(path)
    fileOpenFolder = getPathPart(path)
    saveRecentFiles(fileOpenFolder + fileName)
    setWindowTitle(#WIN1, appName + " - " + path)
  endIf
endProcedure

procedure getLinenumber(id)
  ;gets the linenumber in an editorgadget from the caret position
  setActiveGadget(id)
  getCaretpos_(@pos.point)
  char = sendMessage_(gadgetId(id), #EM_CHARFROMPOS, 0, @pos)
  line =  sendMessage_(gadgetId(id), #EM_LINEFROMCHAR, char, 0)
  procedureReturn line
endProcedure

procedure.s getProgramName(exeName.s)
  ;extracts an application name from an exe name on the form 'c..n...exe'
  ;where c.. are letters and n.. version numbers
  exeName = left(exeName, findString(exeName, ".", 1) - 1)
  for i = 1 to len(exeName)
    C.s = mid(exeName, i, 1)
    if c < "0" or c > "9"
      name.s + c
    endIf
  next i
  procedureReturn rtrim(name)
endProcedure

;-
procedure readPreferences(inFolder.s, name.s)
  #CSIDL_APPDATA = $1A
  ;	XP:     C:\Documents and Settings\username\Application Data*    
  ;	Vista:  C:\Users\username\AppData\Roaming
  if len(inFolder)
    inFolder + "\"
  endIf
  path.s = getPathPart(programFileName())
  type = getDriveType_(left(path, 2))
  if type = 2
    ;removable
    path = path + inFolder + name
  else
    path = getSpecialFolder(#CSIDL_APPDATA) + inFolder + name
  endIf
  openPreferences(path)
  preferenceGroup("metrics")
    maximized = readPreferenceLong("maximized", 0)
    w = GetSystemMetrics_(#SM_CXSCREEN) - 100
    h = GetSystemMetrics_(#SM_CYSCREEN) - 100
    windowW = readPreferenceLong("windowW", w)
    windowH = readPreferenceLong("windowH", h)
  preferenceGroup("files")
    fileOpenFolder = readPreferenceString("fileOpenFolder", getPathPart(getHomeDirectory()))
    fileInsertFolder = readPreferenceString("fileInsertFolder", getPathPart(getHomeDirectory()))
    fileSavetoFolder = readPreferenceString("fileSavetoFolder", getPathPart(getHomeDirectory()))
  preferenceGroup("editor")
    fontName = readPreferenceString("fontName", "courier new")
    fontSize = readPreferenceLong("fontSize", 11)
    fontColor = readPreferenceLong("fontColor", #Black)
    backColor = readPreferenceLong("backColor", rgb(216, 234, 255))
;    backColor = readPreferenceLong("backColor", rgb(255, 255, 255))
  preferenceGroup("recent files")
    recent1 = readPreferenceString("recent1", "[No file]")
    recent2 = readPreferenceString("recent2", "[No file]")
    recent3 = readPreferenceString("recent3", "[No file]")
    recent4 = readPreferenceString("recent4", "[No file]")
    recent5 = readPreferenceString("recent5", "[No file]")
    recent6 = readPreferenceString("recent6", "[No file]")
    recent7 = readPreferenceString("recent7", "[No file]")
    recent8 = readPreferenceString("recent8", "[No File]")
  closePreferences()
endProcedure

procedure writePreferences(inFolder.s, name.s)
  #CSIDL_APPDATA = $1A
  ;	XP:     C:\Documents and Settings\username\Application Data*    
  ;	Vista:  C:\Users\username\AppData\Roaming
  if len(inFolder)
    inFolder + "\"
  endIf
  path.s = getPathPart(programFileName())
  type = getDriveType_(left(path, 2))
  if type = 2
    ;removable
    path = path + inFolder
  else
    path = getSpecialFolder(#CSIDL_APPDATA) + inFolder
  endIf
  createDirectory(path)
  if createPreferences(path + name)
    preferenceGroup("metrics")
      writePreferenceLong("maximized", maximized)
      writePreferenceLong("windowW", windowW)
      writePreferenceLong("windowH", windowH)
    preferenceGroup("files")
      writePreferenceString("fileOpenFolder", fileOpenFolder)
      writePreferenceString("fileInsertFolder", fileInsertFolder)
      writePreferenceString("fileSavetoFolder", fileSavetoFolder)
    preferenceGroup("editor")
      writePreferenceString("fontName", fontName)
      writePreferenceLong("fontSize", fontSize)
      writePreferenceLong("fontColor", fontColor)
      writePreferenceLong("backColor", backColor)
    preferenceGroup("recent files")
      writePreferenceString("recent1", recent1)
      writePreferenceString("recent2", recent2)
      writePreferenceString("recent3", recent3)
      writePreferenceString("recent4", recent4)
      writePreferenceString("recent5", recent5)
      writePreferenceString("recent6", recent6)
      writePreferenceString("recent7", recent7)
      writePreferenceString("recent8", recent8)
    closePreferences()
    procedureReturn 1    
  endIf
  procedureReturn 0
endProcedure

;-
procedure setPreviewSize(wdt, hgt)
  ;sets active panelgadget attached edit/webgadget or window
  ;size to w, h. used to check web page looks at different res
  winW = windowWidth(#WIN1)
  winH = windowHeight(#WIN1)
  if getWindowState(#WIN1) = #PB_WINDOW_MAXIMIZE
    setWindowState(#WIN1, #PB_WINDOW_NORMAL)
    ;or the size gadget disappears!?
  endIf
  if wdt
    ;set preview size, the width (most imporant) will be correct
    edtW = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMWIDTH)
    resizeWindow(#win1, #PB_IGNORE, #PB_IGNORE, winW - edtW + wdt, #PB_IGNORE)
  endIf
  if hgt
    ;height
    edtH = getGadgetAttribute(#PANEL1, #PB_PANEL_ITEMHEIGHT)
    resizeWindow(#WIN1, #PB_IGNORE, #PB_IGNORE, #PB_IGNORE, winH - edtH + hgt)
  endIf
  ;center at top
  lft = (GetSystemMetrics_(#SM_CXSCREEN) - windowWidth(#WIN1)) / 2
  resizeWindow(#WIN1, lft, 0, #PB_IGNORE, #PB_IGNORE)
endProcedure

;-
procedure createShortcut(file, res.s, url.s, icon.s, index)
  ;creates internet shortcuts. res: linked to, url: shortcut path
  ;icon: the path of the icon library file, .ico, .dll or .exe
  ;index: the icon index within the icon library file
  dq.s = chr(34)
  if file
    ;links to a file
    res = "file://" + res
  else
    ;links to a web resource
    res = "http://" + res
  endIf
  if lcase(right(url, 4)) <> ".url"
    url = url + ".url"
  endIf
  ;try to create folders from the top down
  for i = 1 to len(url)
    if mid(url, i, 1) = "\"
      ;create folder:
      createDirectory(left(url, i))   
    endIf
  next
  if createFile(0, url)
    writeStringN(0, "[InternetShortcut]")
    writeStringN(0, "URL = " + dq + res + dq)
    if file
      if len(icon)
        writeStringN(0, "IconFile = " + dq + icon + dq)
        writeStringN(0, "IconIndex = " + dq + str(index) + dq)
      endIf
    endIf
    closeFile(0)
    procedureReturn 1
  endIf
  procedureReturn 0
endProcedure

procedure.s getSpecialFolder(id)
  shGetSpecialFolderLocation_(0, id, @pidl) 
  path.s = space(#MAX_PATH) 
  shGetPathFromIDList_(pidl, @path)
  if right(path, 1) <> "\"
    path + "\"
  endIf
  if pidl 
   coTaskMemFree_(pidl)
  endIf 
  procedureReturn path
endProcedure
Last edited by utopiomania on Wed Jan 30, 2013 4:38 pm, edited 1 time in total.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Re: Htm source editor with preview

Post by utopiomania »

The source is re-posted above in two parts, works with PB5 and runs on Windows 8 :)
infratec
Always Here
Always Here
Posts: 7586
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Htm source editor with preview

Post by infratec »

Hi Utopmania,

I wanted to try your code, but...

Code: Select all

Procedure drawLinenumbers()
  id = GadgetID(#EDIT1)
  hdc = GetDCEx_(id, 0, #DCX_CACHE)
 
  hFont = FontID(GetGadgetFont(#EDIT1))
It stops immediately at the last line:
font not initialized
PB 5.00 x86 Win XP

Bernd
Mohawk70
Enthusiast
Enthusiast
Posts: 404
Joined: Thu May 11, 2006 1:04 am
Location: Florida, USA

Re: Htm source editor with preview

Post by Mohawk70 »

infratec wrote:Hi Utopmania,

I wanted to try your code, but...

Code: Select all

Procedure drawLinenumbers()
  id = GadgetID(#EDIT1)
  hdc = GetDCEx_(id, 0, #DCX_CACHE)
 
  hFont = FontID(GetGadgetFont(#EDIT1))
It stops immediately at the last line:
font not initialized
PB 5.00 x86 Win XP

Bernd
Same here ...
HP Z800 Workstation
CPU : Dual Xeon 5690 3.46GHz
RAM : 96GB RAM ( 8GB x 12 )
PSU : 1100W
GPU : NVIDIA RTX 3050 8GB
STORAGE : 9TB
(4) 2TB Seagate IronWolf Pro HDD
(1) 1TB Samsung 870 EVO SSD
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Htm source editor with preview

Post by electrochrisso »

It will work if you comment that line, and you will also need to comment AddKeyboardShortcut(win, #PB_Shortcut_Return, btn1) in the about procedure too, I suppose these will still need to be fixed, but otherwise it works OK and has a lot of good code to learn from, especially the find and replace for me, thanks for posting Utopmania. :)
PureBasic! Purely the best 8)
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Re: Htm source editor with preview

Post by utopiomania »

Thanks for testing :)
The font issue is fixed:

Code: Select all

;  hFont = fontId(getGadgetFont(#EDIT1))
  hFont = getGadgetFont(#EDIT1)
The about() procedure isn't used in the program and can be removed:

Code: Select all

case #HELP_ABOUT
          helpAbout()
          setActiveGadget(#EDIT1)
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Htm source editor with preview

Post by davido »

Thanks utopiomania, for sharing.

Looks impressive. I, too, will learn a lot from you code. :D
DE AA EB
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: Htm source editor with preview

Post by jassing »

Consider "prefilling" out the editor with the 'bare minimum' shell to get people started.

It doesn't look like title isn't processed -- would be good to show the the title in the window's title bar...
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Re: Htm source editor with preview

Post by utopiomania »

The help system needs som help :) but if you use the program, and needs some help on html syntax,
select it like 'position:absolute' ,then open Tools, W3schools or Google, and the program will search
the site for you for the selected text.

With no selected text it will just open the site for you in the browser.
Post Reply