Merge branches/MarkieB/gtkmain to trunk.

svn path=/trunk/netsurf/; revision=9729
This commit is contained in:
John Mark Bell 2009-12-17 23:55:02 +00:00
parent 4346b2b62b
commit 355799ce0b
127 changed files with 11540 additions and 5251 deletions

View File

@ -0,0 +1,20 @@
Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|
Yahoo|search.yahoo.com|http://search.yahoo.com/search?p=%s|http://www.yahoo.com/favicon.ico|
Bing|www.bing.com|http://www.bing.com/search?q=%s|http://www.bing.com/favicon.ico|
Business.com|www.business.com|http://www.business.com/search/rslt_default.asp?query=%s|http://www.business.com/favicon.ico|
Omgili|www.omgili.com|http://www.omgili.com/AAAAA/%s.html|http://www.omgili.com/favicon.ico|
BBC News|search.bbc.co.uk|http://search.bbc.co.uk/search?q=%s&tab=ns|http://news.bbc.co.uk/favicon.ico|
Ubuntu Packages|packages.ubuntu.com|http://packages.ubuntu.com/search?keywords=%s|http://packages.ubuntu.com/favicon.ico|
Creative Commons|creativecommons.org|http://creativecommons.org/?s=%s|http://creativecommons.org/favicon.ico|
Ask.com|www.ask.com|http://www.ask.com/web?q=%s|http://www.ask.com/favicon.ico|
Answers.com|www.answers.com|http://www.answers.com/%s|http://www.answers.com/favicon.ico|
Dictionary.com|dictionary.reference.com|http://dictionary.reference.com/browse/%s?jss=0|http://dictionary.reference.com/favicon.ico|
Youtube|www.youtube.com|http://www.youtube.com/results?search_query=%s|http://www.youtube.com/favicon.ico|
AeroMp3|www.aeromp3.com|http://www.aeromp3.com/search?q=%s|http://www.aeromp3.com/favicon.ico|
AOL|search.aol.com|http://search.aol.com/aol/search?query=%s|http://www.aol.com/favicon.ico|
Baidu|www.baidu.com|http://www.baidu.com/s?wd=%s|http://www.baidu.com/favicon.ico|
Amazon|www.amazon.com|http://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|http://www.amazon.com/favicon.ico|
Ebay|shop.ebay.com|http://shop.ebay.com/items/%s|http://www.ebay.com/favicon.ico|
IMDB|www.imdb.com|http://www.imdb.com/find?q=%s|http://www.imdb.com/favicon.ico|
ESPN|search.espn.go.com|http://search.espn.go.com/%s/|http://www.espn.go.com/favicon.ico|
Wikipedia|en.wikipedia.org|http://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|http://en.wikipedia.org/favicon.ico|

View File

@ -432,10 +432,118 @@ gtkFailed:Download failed
gtkFileError:File error: %s
gtkInfo:%s from %s is %s in size
gtkSave:Save file as...
gtkSourceSave:Save Source
gtkPlainSave:Save as text
gtkFullSave:Save webpage complete - select an empty directory
gtkUnknownHost:an unknown host
gtkUnknownFile:
gtkUnknownSize:unknown
# gtk Menu / Button labels
#
gtkNewTab:New _Tab
gtkNewTabAccel:<ctrl>t
gtkNewWindow:_New Window
gtkNewWindowAccel:<ctrl>n
gtkOpenFile:_Open File
gtkOpenFileAccel:<ctrl>o
gtkCloseWindow:_Close Window
gtkCloseWindowAccel:<ctrl><shift>w
gtkSavePage:Save Page..
gtkSavePageAccel:<ctrl>s
gtkExport:Export
gtkPlainText:Plain Text..
gtkDrawFile:Drawfile..
gtkPostScript:PostScript..
gtkPDF:PDF..
gtkPrintPreview:Print Preview..
gtkPrintPreviewAccel:<ctrl><shift>p
gtkPrint:Print..
gtkPrintAccel:<ctrl>p
gtkQuit:_Quit
gtkQuitAccel:<ctrl>q
gtkCut:Cu_t
gtkCutAccel:<ctrl>x
gtkCopy:_Copy
gtkCopyAccel:<ctrl>c
gtkPaste:_Paste
gtkPasteAccel:<ctrl>v
gtkDelete:_Delete
gtkSelectAll:Select _All
gtkSelectAllAccel:<ctrl>a
gtkFind:_Find..
gtkFindAccel:<ctrl>f
gtkPreferences:P_references
gtkStop:_Stop
gtkStopAccel:Escape
gtkReload:_Reload
gtkReloadAccel:F5
gtkScaleView:_Scale View
gtkZoomPlus:Zoom _in
gtkZoomPlusAccel:<ctrl>plus
gtkZoomMinus:Zoom _out
gtkZoomMinusAccel:<ctrl>minus
gtkZoomNormal:_Normal size
gtkZoomNormalAccel:<ctrl>0
gtkFullScreen:_Fullscreen
gtkFullScreenAccel:F11
gtkViewSource:View S_ource
gtkViewSourceAccel:F8
gtkImages:_Images
gtkForegroundImages:_Foreground Images
gtkBackgroundImages:_Background Images
gtkToolbars:_Toolbars
gtkMenuBar:_Menu Bar
gtkToolBar:_Button Bar
gtkStatusBar:_Status Bar
gtkDownloads:_Downloads
gtkDownloadsAccel:<ctrl>d
gtkSaveWindowSize:S_ave Window Size
gtkDebugging:De_bugging
gtkToggleDebugging:T_oggle debug rendering
gtkSaveBoxTree:_Save box tree
gtkSaveDomTree:Save DOM tree
gtkBack:_Back
gtkBackAccel:<alt>Left
gtkForward:_Forward
gtkForwardAccel:<alt>Right
gtkHome:_Home
gtkHomeAccel:<alt>Down
gtkLocalHistory:_Local History
gtkLocalHistoryAccel:<ctrl>h
gtkGlobalHistory:_Global History
gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks..
gtkShowBookMarks:_Show Bookmarks..
gtkShowBookMarksAccel:F6
gtkOpenLocation:_Open Location..
gtkOpenLocationAccel:<ctrl>l
gtkNextTab:_Next tab
gtkNextTabAccel:<ctrl>Right
gtkPrevTab:_Previous tab
gtkPrevTabAccel:<ctrl>Left
gtkCloseTab:_Close tab
gtkCloseTabAccel:<ctrl>w
gtkContents:_Contents
gtkGuide:User _guide
gtkUserInformation:User _information
gtkAbout:_About
gtkToolBarTitle:Toolbar custom button store
gtkAddThemeTitle:Select folder containing theme images
gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
gtkThemeFolderSub:Select a subdirectory of the themes folder
gtkThemeDup:Theme is already included
gtkThemeAdd:Theme added successfully
# Printing user interface tokens
# ==============================
#
@ -459,6 +567,8 @@ Printing:Printing page
NotFound:nichts
Next:Next
Prev:Previous
ShowAll:Show All
CaseSens:Case Sensitive
# 401 login user interface tokens
@ -578,6 +688,9 @@ MiscError:Unerwarteter Fehler:
FileError:Datei existiert nicht:
PrintError:Ein Fehler trat während des Druckens auf:
AWNotSeen:Das Programm AWViewer wurde nicht gefunden.
EncNotRec:Encoding type not recognised.
FileOpenError:could not open file '%s'
DirectoryError:directory '%s' already exists
# Specific errors - displayed in a dialog box
#
@ -589,11 +702,13 @@ NoDiscSpace:Nicht genug Speicherplatz auf dem Medium vorhanden.
Template:Ein Template für ein Fenster fehlt in der Datei Templates. Bitte NetSurf neu installieren.
HotlistSaveError:Hotlist konnte nicht korrekt gespeichert werden.
HotlistLoadError:Hotlist konnte nicht korrekt geladen werden.
NoDirError:%s is not a directory
NoPathError:Symbol in ein Verzeichnisfenster ziehen um zu Speichern.
NoNameError:Bitte einen Namen eingeben.
NoURLError:Bitte eine URL Adresse eingeben.
URIError:NetSurf konnte die URI Datei nicht lesen. Syntax Fehler.
EmptyError:Die Datei ist leer.
SearchError:Invalid Search.
PrintErrorRO2:Der Drucker scheint beschäftigt zu sein.
AWNotSeen:Please locate the AWViewer application and try again.
@ -636,6 +751,7 @@ Done:Dokument fertiggestellt
BadRedirect:Falsche URL für Redirect
FetchFailed:Kann Dokument nicht fetchen
NotCSS:Warnung: Stylesheet ist kein CSS
NotFavIco:Favicon not supported
BadObject:Warnung: falscher Objekttyp
ObjError:Fehler beim Laden des Objektes: %s
ParsingFail:Dokumentparsing ist fehlgeschlagen.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -434,12 +434,119 @@ gtkFileError:File error: %s
gtkInfo:%s from %s is %s in size
gtkSave:Save file as...
gtkSourceSave:Save source
gtkplainSave:Save plain text
gtkcompleteSave:Save webpage complete - select an empty directory
gtkSaveConfirm:File saved
gtkSaveCancelled:File not saved
gtkUnknownHost:an unknown host
gtkUnknownFile:
gtkUnknownSize:unknown
# gtk Menu / Button labels
#
gtkNewTab:New _Tab
gtkNewTabAccel:<ctrl>t
gtkNewWindow:_New Window
gtkNewWindowAccel:<ctrl>n
gtkOpenFile:_Open File
gtkOpenFileAccel:<ctrl>o
gtkCloseWindow:_Close Window
gtkCloseWindowAccel:<ctrl><shift>w
gtkSavePage:Save Page..
gtkSavePageAccel:<ctrl>s
gtkExport:Export
gtkPlainText:Plain Text..
gtkDrawFile:Drawfile..
gtkPostScript:PostScript..
gtkPDF:PDF..
gtkPrintPreview:Print Preview..
gtkPrintPreviewAccel:<ctrl><shift>p
gtkPrint:Print..
gtkPrintAccel:<ctrl>p
gtkQuitMenu:_Quit
gtkQuitMenuAccel:<ctrl>q
gtkCut:Cu_t
gtkCutAccel:<ctrl>x
gtkCopy:_Copy
gtkCopyAccel:<ctrl>c
gtkPaste:_Paste
gtkPasteAccel:<ctrl>v
gtkDelete:_Delete
gtkSelectAll:Select _All
gtkSelectAllAccel:<ctrl>a
gtkFind:_Find..
gtkFindAccel:<ctrl>f
gtkPreferences:P_references
gtkStop:_Stop
gtkStopAccel:Escape
gtkReload:_Reload
gtkReloadAccel:F5
gtkScaleView:_Scale View
gtkZoomPlus:Zoom _in
gtkZoomPlusAccel:<ctrl>plus
gtkZoomMinus:Zoom _out
gtkZoomMinusAccel:<ctrl>minus
gtkZoomNormal:_Normal size
gtkZoomNormalAccel:<ctrl>0
gtkFullScreen:_Fullscreen
gtkFullScreenAccel:F11
gtkViewSource:View S_ource
gtkViewSourceAccel:F8
gtkImages:_Images
gtkForegroundImages:_Foreground Images
gtkBackgroundImages:_Background Images
gtkToolbars:_Toolbars
gtkMenuBar:_Menu Bar
gtkToolBar:_Button Bar
gtkStatusBar:_Status Bar
gtkDownloads:_Downloads
gtkDownloadsAccel:<ctrl>d
gtkSaveWindowSize:S_ave Window Size
gtkDebugging:De_bugging
gtkToggleDebugging:T_oggle debug rendering
gtkSaveBoxTree:_Save box tree
gtkSaveDomTree:Save DOM tree
gtkBack:_Back
gtkBackAccel:<alt>Left
gtkForward:_Forward
gtkForwardAccel:<alt>Right
gtkHome:_Home
gtkHomeAccel:<alt>Down
gtkLocalHistory:_Local History
gtkLocalHistoryAccel:<ctrl>h
gtkGlobalHistory:_Global History
gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks..
gtkShowBookMarks:_Show Bookmarks..
gtkShowBookMarksAccel:F6
gtkOpenLocation:_Open Location..
gtkOpenLocationAccel:<ctrl>l
gtkNextTab:_Next tab
gtkNextTabAccel:<ctrl>Right
gtkPrevTab:_Previous tab
gtkPrevTabAccel:<ctrl>Left
gtkCloseTab:_Close tab
gtkCloseTabAccel:<ctrl>w
gtkContents:_Contents
gtkGuide:User _guide
gtkUserInformation:User _information
gtkAbout:_About
gtkToolBarTitle:Toolbar custom button store
gtkAddThemeTitle:Select folder containing theme images
gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
gtkThemeFolderSub:Select a subdirectory of the themes folder
gtkThemeDup:Theme is already included
gtkThemeAdd:Theme added successfully
# Printing user interface tokens
# ==============================
#
@ -463,6 +570,8 @@ Printing:Printing page
NotFound:Not found
Next:Next
Prev:Previous
ShowAll:Show All
CaseSens:Case Sensitive
# 401 login user interface tokens
@ -593,14 +702,18 @@ NoDiscSpace:Not enough space available on disc.
Template:A window template is missing from the Templates file. Please reinstall NetSurf.
HotlistSaveError:The hotlist was unable to be correctly saved.
HotlistLoadError:The hotlist was unable to be correctly loaded.
NoDirError:%s is not a directory
NoPathError:To save, drag the icon to a directory display
NoNameError:Please enter a name
NoURLError:Please enter a URL
URIError:NetSurf was unable to parse this URI file due to a syntax error.
EmptyError:file is empty.
SearchError:Invalid Search.
PrintErrorRO2:It appears that the printer is busy.
AWNotSeen:Please locate the AWViewer application and try again.
EncNotRec:Encoding type not recognised.
FileOpenError:could not open file '%s'
DirectoryError:directory '%s' already exists
# Error messages for Amiga version only
CompError:Unable to open
@ -641,6 +754,7 @@ Done:Document done
BadRedirect:Bad redirect URL
FetchFailed:Unable to fetch document
NotCSS:Warning: stylesheet is not CSS
NotFavIco:Favicon not supported
BadObject:Warning: bad object type
ObjError:Error loading object: %s
ParsingFail:Parsing the document failed.

View File

@ -432,10 +432,118 @@ gtkFailed:Download failed
gtkFileError:File error: %s
gtkInfo:%s from %s is %s in size
gtkSave:Save file as...
gtkSourceSave:Save Source
gtkPlainSave:Save as text
gtkFullSave:Save webpage complete - select an empty directory
gtkUnknownHost:an unknown host
gtkUnknownFile:
gtkUnknownSize:unknown
# gtk Menu / Button labels
#
gtkNewTab:New _Tab
gtkNewTabAccel:<ctrl>t
gtkNewWindow:_New Window
gtkNewWindowAccel:<ctrl>n
gtkOpenFile:_Open File
gtkOpenFileAccel:<ctrl>o
gtkCloseWindow:_Close Window
gtkCloseWindowAccel:<ctrl><shift>w
gtkSavePage:Save Page..
gtkSavePageAccel:<ctrl>s
gtkExport:Export
gtkPlainText:Plain Text..
gtkDrawFile:Drawfile..
gtkPostScript:PostScript..
gtkPDF:PDF..
gtkPrintPreview:Print Preview..
gtkPrintPreviewAccel:<ctrl><shift>p
gtkPrint:Print..
gtkPrintAccel:<ctrl>p
gtkQuit:_Quit
gtkQuitAccel:<ctrl>q
gtkCut:Cu_t
gtkCutAccel:<ctrl>x
gtkCopy:_Copy
gtkCopyAccel:<ctrl>c
gtkPaste:_Paste
gtkPasteAccel:<ctrl>v
gtkDelete:_Delete
gtkSelectAll:Select _All
gtkSelectAllAccel:<ctrl>a
gtkFind:_Find..
gtkFindAccel:<ctrl>f
gtkPreferences:P_references
gtkStop:_Stop
gtkStopAccel:Escape
gtkReload:_Reload
gtkReloadAccel:F5
gtkScaleView:_Scale View
gtkZoomPlus:Zoom _in
gtkZoomPlusAccel:<ctrl>plus
gtkZoomMinus:Zoom _out
gtkZoomMinusAccel:<ctrl>minus
gtkZoomNormal:_Normal size
gtkZoomNormalAccel:<ctrl>0
gtkFullScreen:_Fullscreen
gtkFullScreenAccel:F11
gtkViewSource:View S_ource
gtkViewSourceAccel:F8
gtkImages:_Images
gtkForegroundImages:_Foreground Images
gtkBackgroundImages:_Background Images
gtkToolbars:_Toolbars
gtkMenuBar:_Menu Bar
gtkToolBar:_Button Bar
gtkStatusBar:_Status Bar
gtkDownloads:_Downloads
gtkDownloadsAccel:<ctrl>d
gtkSaveWindowSize:S_ave Window Size
gtkDebugging:De_bugging
gtkToggleDebugging:T_oggle debug rendering
gtkSaveBoxTree:_Save box tree
gtkSaveDomTree:Save DOM tree
gtkBack:_Back
gtkBackAccel:<alt>Left
gtkForward:_Forward
gtkForwardAccel:<alt>Right
gtkHome:_Home
gtkHomeAccel:<alt>Down
gtkLocalHistory:_Local History
gtkLocalHistoryAccel:<ctrl>h
gtkGlobalHistory:_Global History
gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks..
gtkShowBookMarks:_Show Bookmarks..
gtkShowBookMarksAccel:F6
gtkOpenLocation:_Open Location..
gtkOpenLocationAccel:<ctrl>l
gtkNextTab:_Next tab
gtkNextTabAccel:<ctrl>Right
gtkPrevTab:_Previous tab
gtkPrevTabAccel:<ctrl>Left
gtkCloseTab:_Close tab
gtkCloseTabAccel:<ctrl>w
gtkContents:_Contents
gtkGuide:User _guide
gtkUserInformation:User _information
gtkAbout:_About
gtkToolBarTitle:Toolbar custom button store
gtkAddThemeTitle:Select folder containing theme images
gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
gtkThemeFolderSub:Select a subdirectory of the themes folder
gtkThemeDup:Theme is already included
gtkThemeAdd:Theme added successfully
# Printing user interface tokens
# ==============================
#
@ -459,6 +567,8 @@ Printing:Printing page
NotFound:Non trouvé
Next:Next
Prev:Previous
ShowAll:Show All
CaseSens:Case Sensitive
# 401 login user interface tokens
@ -578,6 +688,9 @@ MiscError:Une erreur inattendue s'est produite:
FileError:Le fichier n'existe pas:
PrintError:Une erreur s'est produite lors de l'impression:
AWNotSeen:Localisez l'application AMViewer SVP puis réessayez.
EncNotRec:Encoding type not recognised.
FileOpenError:could not open file '%s'
DirectoryError:directory '%s' already exists
# Specific errors - displayed in a dialog box
#
@ -589,11 +702,13 @@ NoDiscSpace:Pas assez d'espace disque disponible.
Template:Un modèle de fenêtre est absent du fichier Templates. Réinstallez NetSurf SVP.
HotlistSaveError:Les favoris n'ont pas pu être sauvés correctement.
HotlistLoadError:Les favoris n'ont pas pu être chargés correctement.
NoDirError:%s n'est pas un répertoire
NoPathError:Pour sauver, lâcher cette icône dans une fenêtre de Filer
NoNameError:Entrez un nom SVP
NoURLError:Entrez une URL SVP
URIError:NetSurf est incapable de traiter ce fichier URI à cause d'une erreur de syntaxe.
EmptyError:Le fichier est vide.
SearchError:Recherche Non-Valide.
PrintErrorRO2:Il semble que l'imprimante soit occupée.
AWNotSeen:Localisez l'application AMViewer SVP puis réessayez.
@ -636,6 +751,7 @@ Done:Document terminé
BadRedirect:Mauvais URL de redirection
FetchFailed:Récupération du fichier impossible
NotCSS:Attention: feuille de style non CSS
NotFavIco:Favicon non-soutenu
BadObject:Attention: mauvais type d'objet
ObjError:Erreur lors du chargement de: %s
ParsingFail:L'analyse syntaxique du document a échoué.

View File

@ -214,7 +214,7 @@ URLSuggest:URL Recenti
Languages:Lingua
#
# Network pane
ProxyType:Tipo di proxy
ProxyType:Tipo di Proxy
ProxyNone:Nessun proxy
ProxyNoAuth:Proxy semplice
ProxyBasic:Autentificazione di Base
@ -437,12 +437,119 @@ gtkFileError:Errore File: %s
gtkInfo:%s da %s è %s come dimensione
gtkSave:Salva file come...
gtkSourceSave:Salva sorgente
gtkPlainSave:Save as text
gtkFullSave:Save webpage complete - select an empty directory
gtkSaveConfirm:File salvato
gtkSaveCancelled:File non salvato
gtkUnknownHost:un Host sconosciuto
gtkUnknownFile:
gtkUnknownSize:sconosciuto
# gtk Menu / Button labels
#
gtkNewTab:New _Tab
gtkNewTabAccel:<ctrl>t
gtkNewWindow:_New Window
gtkNewWindowAccel:<ctrl>n
gtkOpenFile:_Open File
gtkOpenFileAccel:<ctrl>o
gtkCloseWindow:_Close Window
gtkCloseWindowAccel:<ctrl><shift>w
gtkSavePage:Save Page..
gtkSavePageAccel:<ctrl>s
gtkExport:Export
gtkPlainText:Plain Text..
gtkDrawFile:Drawfile..
gtkPostScript:PostScript..
gtkPDF:PDF..
gtkPrintPreview:Print Preview..
gtkPrintPreviewAccel:<ctrl><shift>p
gtkPrint:Print..
gtkPrintAccel:<ctrl>p
gtkQuit:_Quit
gtkQuitAccel:<ctrl>q
gtkCut:Cu_t
gtkCutAccel:<ctrl>x
gtkCopy:_Copy
gtkCopyAccel:<ctrl>c
gtkPaste:_Paste
gtkPasteAccel:<ctrl>v
gtkDelete:_Delete
gtkSelectAll:Select _All
gtkSelectAllAccel:<ctrl>a
gtkFind:_Find..
gtkFindAccel:<ctrl>f
gtkPreferences:P_references
gtkStop:_Stop
gtkStopAccel:Escape
gtkReload:_Reload
gtkReloadAccel:F5
gtkScaleView:_Scale View
gtkZoomPlus:Zoom _in
gtkZoomPlusAccel:<ctrl>plus
gtkZoomMinus:Zoom _out
gtkZoomMinusAccel:<ctrl>minus
gtkZoomNormal:_Normal size
gtkZoomNormalAccel:<ctrl>0
gtkFullScreen:_Fullscreen
gtkFullScreenAccel:F11
gtkViewSource:View S_ource
gtkViewSourceAccel:F8
gtkImages:_Images
gtkForegroundImages:_Foreground Images
gtkBackgroundImages:_Background Images
gtkToolbars:_Toolbars
gtkMenuBar:_Menu Bar
gtkToolBar:_Button Bar
gtkStatusBar:_Status Bar
gtkDownloads:_Downloads
gtkDownloadsAccel:<ctrl>d
gtkSaveWindowSize:S_ave Window Size
gtkDebugging:De_bugging
gtkToggleDebugging:T_oggle debug rendering
gtkSaveBoxTree:_Save box tree
gtkSaveDomTree:Save DOM tree
gtkBack:_Back
gtkBackAccel:<alt>Left
gtkForward:_Forward
gtkForwardAccel:<alt>Right
gtkHome:_Home
gtkHomeAccel:<alt>Down
gtkLocalHistory:_Local History
gtkLocalHistoryAccel:<ctrl>h
gtkGlobalHistory:_Global History
gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks..
gtkShowBookMarks:_Show Bookmarks..
gtkShowBookMarksAccel:F6
gtkOpenLocation:_Open Location..
gtkOpenLocationAccel:<ctrl>l
gtkNextTab:_Next tab
gtkNextTabAccel:<ctrl>Right
gtkPrevTab:_Previous tab
gtkPrevTabAccel:<ctrl>Left
gtkCloseTab:_Close tab
gtkCloseTabAccel:<ctrl>w
gtkContents:_Contents
gtkGuide:User _guide
gtkUserInformation:User _information
gtkAbout:_About
gtkToolBarTitle:Toolbar custom button store
gtkAddThemeTitle:Select folder containing theme images
gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
gtkThemeFolderSub:Select a subdirectory of the themes folder
gtkThemeDup:Theme is already included
gtkThemeAdd:Theme added successfully
# Printing user interface tokens
# ==============================
#
@ -466,6 +573,8 @@ Printing:Stampa della pagina
NotFound:Non trovato
Next:Successivo
Prev:Precedente
ShowAll:Show All
CaseSens:Case Sensitive
# 401 login user interface tokens
# ===============================
@ -487,17 +596,17 @@ Cancel:Annulla
# This section contains tokens which are used in the
# SSL certificate verification dialog box.
#
SSLCerts:Certificati SSL
SSLError:NetSurf non è stato in grado di verificare l'autenticità del certificato SSL. Per favore verifica i dettagli qui sotto elencati.
Subject:Oggetto
Issuer:Depositario
Version:Versione
ValidFrom:Valido da
ValidTo:Valido fino
Type:Tipo
Serial:Seriale
Accept:Accetta
Reject:Rifiuta
SSLCerts:SSL certificates
SSLError:NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.
Subject:Subject
Issuer:Issuer
Version:Version
ValidFrom:Valid from
ValidTo:Valid until
Type:Type
Serial:Serial
Accept:Accept
Reject:Reject
# Content
@ -584,6 +693,9 @@ MiscError:Si è verificato un errore inatteso:
FileError:Il file è inesistente:
PrintError:Si è verificato un errore durante la stampa:
AWNotSeen:Per favore imposta l'applicazione AWViewer e riprova ancora.
EncNotRec:Encoding type not recognised.
FileOpenError:could not open file '%s'
DirectoryError:directory '%s' already exists
# Specific errors - displayed in a dialog box
#
@ -595,10 +707,12 @@ NoDiscSpace:Spazio insufficiente nel disco.
Template:Una finestra di template risulta mancante. Per favore reinstalla NetSurf.
HotlistSaveError:Non è stato possibile salvare correttamente i segnalibri.
HotlistLoadError:Non è stato possibile caricare correttamente i segnalibri.
NoDirError:%s is not a directory
NoPathError:Per salvare, trascinare l'icona in una directory di visualizzazione.
NoNameError:Inserisci un nome
NoURLError:Inserisci un URL
URIError:NetSurf non è stato in grado di processare questo file URI a causa di un errore di sintassi.
SearchError:Invalid Search.
EmptyError:Il file è vuoto.
PrintErrorRO2:Sembra che la stampante sia occupata.
AWNotSeen:Per favore imposta l'applicazione AWViewer e riprova ancora.
@ -642,7 +756,8 @@ Done:Documento completato
#
BadRedirect:Errata redirezione dell'URL
FetchFailed:Impossibile ottenere il documento
NotCSS:Attenzione: la dicitura "Foglio di stile" non ha nulla a che vedere con i CSS
NotCSS:Attenzione: "Foglio di stile" non ha nulla a che spartire con i CSS
NotFavIco:Favicon not supported
BadObject:Attenzione: errato tipo di oggetto
ObjError:Errore di caricamento dell'oggetto: %s
ParsingFail:Analisi del documento fallita.
@ -678,7 +793,7 @@ HTTP404:Non trovato
HTTP405:Metodo non permesso
HTTP406:Non accettabile
HTTP407:Autentificazione Proxy necessaria
HTTP408:Messaggio di TimeOut
HTTP408:Richiesta TimeOut
HTTP409:Conflitto
HTTP410:Irraggiungibile
HTTP411:Lunghezza richiesta

View File

@ -432,10 +432,118 @@ gtkFailed:Download failed
gtkFileError:File error: %s
gtkInfo:%s from %s is %s in size
gtkSave:Save file as...
gtkSourceSave:Save Source
gtkPlainSave:Save as text
gtkFullSave:Save webpage complete - select an empty directory
gtkUnknownHost:an unknown host
gtkUnknownFile:
gtkUnknownSize:unknown
# gtk Menu / Button labels
#
gtkNewTab:New _Tab
gtkNewTabAccel:<ctrl>t
gtkNewWindow:_New Window
gtkNewWindowAccel:<ctrl>n
gtkOpenFile:_Open File
gtkOpenFileAccel:<ctrl>o
gtkCloseWindow:_Close Window
gtkCloseWindowAccel:<ctrl><shift>w
gtkSavePage:Save Page..
gtkSavePageAccel:<ctrl>s
gtkExport:Export
gtkPlainText:Plain Text..
gtkDrawFile:Drawfile..
gtkPostScript:PostScript..
gtkPDF:PDF..
gtkPrintPreview:Print Preview..
gtkPrintPreviewAccel:<ctrl><shift>p
gtkPrint:Print..
gtkPrintAccel:<ctrl>p
gtkQuit:_Quit
gtkQuitAccel:<ctrl>q
gtkCut:Cu_t
gtkCutAccel:<ctrl>x
gtkCopy:_Copy
gtkCopyAccel:<ctrl>c
gtkPaste:_Paste
gtkPasteAccel:<ctrl>v
gtkDelete:_Delete
gtkSelectAll:Select _All
gtkSelectAllAccel:<ctrl>a
gtkFind:_Find..
gtkFindAccel:<ctrl>f
gtkPreferences:P_references
gtkStop:_Stop
gtkStopAccel:Escape
gtkReload:_Reload
gtkReloadAccel:F5
gtkScaleView:_Scale View
gtkZoomPlus:Zoom _in
gtkZoomPlusAccel:<ctrl>plus
gtkZoomMinus:Zoom _out
gtkZoomMinusAccel:<ctrl>minus
gtkZoomNormal:_Normal size
gtkZoomNormalAccel:<ctrl>0
gtkFullScreen:_Fullscreen
gtkFullScreenAccel:F11
gtkViewSource:View S_ource
gtkViewSourceAccel:F8
gtkImages:_Images
gtkForegroundImages:_Foreground Images
gtkBackgroundImages:_Background Images
gtkToolbars:_Toolbars
gtkMenuBar:_Menu Bar
gtkToolBar:_Button Bar
gtkStatusBar:_Status Bar
gtkDownloads:_Downloads
gtkDownloadsAccel:<ctrl>d
gtkSaveWindowSize:S_ave Window Size
gtkDebugging:De_bugging
gtkToggleDebugging:T_oggle debug rendering
gtkSaveBoxTree:_Save box tree
gtkSaveDomTree:Save DOM tree
gtkBack:_Back
gtkBackAccel:<alt>Left
gtkForward:_Forward
gtkForwardAccel:<alt>Right
gtkHome:_Home
gtkHomeAccel:<alt>Down
gtkLocalHistory:_Local History
gtkLocalHistoryAccel:<ctrl>h
gtkGlobalHistory:_Global History
gtkGlobalHistoryAccel:<ctrl><shift>h
gtkAddBookMarks:_Add to Bookmarks..
gtkShowBookMarks:_Show Bookmarks..
gtkShowBookMarksAccel:F6
gtkOpenLocation:_Open Location..
gtkOpenLocationAccel:<ctrl>l
gtkNextTab:_Next tab
gtkNextTabAccel:<ctrl>Right
gtkPrevTab:_Previous tab
gtkPrevTabAccel:<ctrl>Left
gtkCloseTab:_Close tab
gtkCloseTabAccel:<ctrl>w
gtkContents:_Contents
gtkGuide:User _guide
gtkUserInformation:User _information
gtkAbout:_About
gtkToolBarTitle:Toolbar custom button store
gtkAddThemeTitle:Select folder containing theme images
gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
gtkThemeFolderSub:Select a subdirectory of the themes folder
gtkThemeDup:Theme is already included
gtkThemeAdd:Theme added successfully
# Printing user interface tokens
# ==============================
#
@ -459,6 +567,8 @@ Printing:Printing page
NotFound:Niet gevonden
Next:Next
Prev:Previous
ShowAll:Show All
CaseSens:Case Sensitive
# 401 login user interface tokens
@ -578,6 +688,9 @@ MiscError:Er trad een onverwachtte fout op:
FileError:Bestand bestaat niet:
PrintError:Fout tijdens printen:
AWNotSeen:Zoek eerst de AWViewer applicatie en probeer het dan nog eens.
EncNotRec:Encoding type not recognised.
FileOpenError:could not open file '%s'
DirectoryError:directory '%s' already exists
# Specific errors - displayed in a dialog box
#
@ -589,10 +702,12 @@ NoDiscSpace:Niet genoeg ruimte beschikbaar op disk.
Template:Er ontbreekt een venster sjabloon in het Templates bestand. Installeer NetSurf opnieuw.
HotlistSaveError:The hotlist was unable to be correctly saved.
HotlistLoadError:The hotlist was unable to be correctly loaded.
NoDirError:%s is not a directory
NoPathError:Sleep het icoon naar een bestandsvenster om het op te slaan.
NoNameError:Geef een naam op
NoURLError:Geef een URL op
URIError:NetSurf was unable to parse this URI file due to a syntax error.
SearchError:Invalid Search.
EmptyError:bestand is leeg.
PrintErrorRO2:De printer lijkt al bezig te zijn.
AWNotSeen:Please locate the AWViewer application and try again.
@ -636,6 +751,7 @@ Done:klaar
BadRedirect:foutief doorverwijzen naar URL
FetchFailed:kan dit document niet ophalen
NotCSS:melding: stylesheet is geen CSS
NotFavIco:Favicon not supported
BadObject:melding: fout object type
ObjError:fout bij laden object: %s
ParsingFail:fout bij ontleden van dit document.

102
Docs/BUILDING-AmigaCross Normal file
View File

@ -0,0 +1,102 @@
to install an Amiga cross-compiler in a Linux distribution, there are instructions at
http://utilitybase.com/article/show/2007/06/23/231/Installing+an+AmigaOS+4+cross+compiler
a more Mac-oriented article [though of potentially general utility] is at
http://utilitybase.com/article/show/2006/05/21/188/Building+Amiga+OS+4+GCC+Cross+Compiler+for+UNIX%252FMAC
more background at
http://cross.zerohero.se/os4.html
cross-compile additional libs/tools
SDK
http://www.hyperion-entertainment.biz/
newlib
http://sources.redhat.com/newlib/
clib2
http://sourceforge.net/projects/clib2/
ixemul
http://strohmayer.org/sfs/
libnix
http://sourceforge.net/projects/libnix/
though newlib / clib2 are apparently already included in the ppc-amigaos-gcc tarball
lha utility is debian package lha
then install linked libs in the correct place
[normally /usr/local/amiga]
so
sudo chmod --recursive 775 /usr/local/amiga
sudo chmod --recursive +s /usr/local/amiga
sudo chown --recursive `whoami` /usr/local/amiga
sudo chgrp --recursive root /usr/local/amiga
[mkdir /usr/local/amiga/include]
[may need to set ppc-amigaos-gcc libpaths]
zlib
download tarball from project homepage, untar in a storage directory /
download source from your distribution's repository [zlib1g in Ubuntu]
[cd to top-level directory of zlib containing configure script]
CC=ppc-amigaos-gcc AR=ppc-amigaos-ar RANLIB=ppc-amigaos-ranlib \
CFLAGS="-DNO_FSEEKO" ./configure --prefix=/usr/local/amiga
make
make install
libxml
download the tarball from the project's homepage, untar in a storage directory /
download source from your distribution's repository
download the tarball from the project's homepage, untar in a storage directory /
download source from your distribution's repository
cd into the directory containing the configure file
$ ./configure --prefix=/usr/local/amiga --host=ppc-amigaos
$ make
[need glob.h / change logic in runtest.c]
$ make install
alternative
http://www.aminet.net/dev/lib/libxml.lha
regex [pre-compiled]
http://aminet.net/dev/lib/libregex-4.4.3.lha
libcurl
download the tarball from the project's homepage, untar in a storage directory /
download source from your distribution's repository
cd into the directory containing the configure file
./configure --prefix=/usr/local/amiga --host=ppc-amigaos
$ make
[you MUST have either POSIX or glibc strerror_r if strerror_r is found]
$ make install
alternative
http://www.aminet.net/dev/lib/libcurl.lha
libiconv [unnecessary as a non-overridable limited version is included in newlib]
openssl
libpng
libmng
http://www.aminet.net/dev/lib/libmng_so.lha
http://www.aminet.net/dev/lib/libmng.lha
liblcms
http://www.aminet.net/dev/lib/liblcms_so.lha
http://www.aminet.net/dev/lib/liblcms_so.lha
libjpeg
libparserutils
libhubbub
libcss
libnsbmp
libnsgif

View File

@ -896,6 +896,8 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED = riscos CSS_INTERNALS WITH_ARTWORKS WITH_BMP WITH_DRAW WITH_DRAW_EXPORT WITH_GIF WITH_JPEG WITH_MMAP WITH_MNG WITH_NSSPRITE WITH_NS_SVG WITH_PLUGIN WITH_RSVG WITH_SAVE_COMPLETE WITH_SPRITE WITH_THEME_INSTALL WITH_PDF_EXPORT
PREDEFINED = gtk WITH_THEME_INSTALL
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.

View File

@ -109,6 +109,11 @@ STRIP=strip
# Override this only if the host compiler is called something different
HOST_CC := gcc
ifeq ($(TARGET),amiga)
ifneq ($(HOST),amiga)
CC := ppc-amigaos-gcc
endif
endif
ifeq ($(TARGET),riscos)
ifeq ($(HOST),riscos)
@ -550,6 +555,9 @@ else
$(Q)$(ELF2AIF) $(EXETARGET:,ff8=,e1f) $(EXETARGET)
$(Q)$(RM) $(EXETARGET:,ff8=,e1f)
endif
ifeq ($(TARGET),gtk)
$(Q)$(TOUCH) gtk/res/toolbarIndices
endif
ifeq ($(NETSURF_STRIP_BINARY),YES)
$(VQ)echo " STRIP: $(EXETARGET)"
$(Q)$(STRIP) $(EXETARGET)
@ -749,10 +757,13 @@ install-gtk: nsgtk
@cp -vRL gtk/res/Aliases $(DESTDIR)$(NETSURF_GTK_RESOURCES)
@cp -vrL gtk/res/docs $(DESTDIR)/$(NETSURF_GTK_RESOURCES)
gzip -9v < gtk/res/messages > $(DESTDIR)$(NETSURF_GTK_RESOURCES)messages
gzip -9v < gtk/res/SearchEngines > $(DESTDIR)$(NETSURF_GTK_RESOURCES)SearchEngines
gzip -9v < gtk/res/downloads.glade > $(DESTDIR)$(NETSURF_GTK_RESOURCES)downloads.glade
gzip -9v < gtk/res/netsurf.glade > $(DESTDIR)$(NETSURF_GTK_RESOURCES)netsurf.glade
gzip -9v < gtk/res/options.glade > $(DESTDIR)$(NETSURF_GTK_RESOURCES)options.glade
gzip -9v < gtk/res/history.glade > $(DESTDIR)$(NETSURF_GTK_RESOURCES)history.glade
gzip -9v < gtk/res/toolbar.glade >
$(DESTDIR)$(NETSURF_GTK_RESOURCES)toolbar.glade
gzip -9v < gtk/res/source.glade > $(DESTDIR)$(NETSURF_GTK_RESOURCES)source.glade
install-beos: NetSurf

View File

@ -8,13 +8,13 @@
S_CONTENT := content.c fetch.c fetchcache.c urldb.c \
fetchers/fetch_curl.c fetchers/fetch_data.c
S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c directory.c \
S_RENDER := box.c box_construct.c box_normalise.c directory.c favicon.c \
font.c form.c html.c html_redraw.c hubbub_binding.c imagemap.c \
layout.c list.c table.c textplain.c
S_UTILS := base64.c filename.c hashtable.c locale.c messages.c talloc.c \
url.c utf8.c utils.c useragent.c
S_DESKTOP := knockout.c options.c print.c tree.c version.c textarea.c \
plot_style.c scroll.c
S_UTILS := base64.c filename.c hashtable.c locale.c \
messages.c talloc.c url.c utf8.c utils.c useragent.c
S_DESKTOP := knockout.c options.c plot_style.c print.c search.c \
searchweb.c scroll.c textarea.c tree.c version.c
# S_COMMON are sources common to all builds
S_COMMON := $(addprefix content/,$(S_CONTENT)) \
@ -33,8 +33,8 @@ S_PDF := $(addprefix desktop/save_pdf/,$(S_PDF))
# S_BROWSER are sources related to full browsers but are common
# between RISC OS, GTK, BeOS and AmigaOS builds
S_BROWSER := browser.c frames.c history_core.c netsurf.c save_text.c \
selection.c textinput.c
S_BROWSER := browser.c frames.c history_core.c netsurf.c save_complete.c \
save_text.c selection.c textinput.c
S_BROWSER := $(addprefix desktop/,$(S_BROWSER))
# S_RISCOS are sources purely for the RISC OS build
@ -42,9 +42,9 @@ S_RISCOS := 401login.c artworks.c assert.c awrender.s bitmap.c buffer.c \
cookies.c configure.c debugwin.c dialog.c download.c draw.c \
filetype.c font.c global_history.c gui.c help.c history.c \
hotlist.c image.c menus.c message.c palettes.c plotters.c \
plugin.c print.c query.c save.c save_complete.c save_draw.c \
save_pdf.c schedule.c search.c sprite.c sslcert.c textarea.c \
textselection.c theme.c theme_install.c thumbnail.c \
plugin.c print.c query.c save.c save_draw.c save_pdf.c \
schedule.c search.c searchweb.c sprite.c sslcert.c \
textarea.c textselection.c theme.c theme_install.c thumbnail.c \
treeview.c ucstables.c uri.c url_complete.c url_protocol.c \
wimp.c wimp_event.c window.c gui/progress_bar.c \
gui/status_bar.c \
@ -60,16 +60,19 @@ S_GTK := font_pango.c gtk_bitmap.c gtk_gui.c gtk_schedule.c \
gtk_thumbnail.c gtk_plotters.c gtk_treeview.c gtk_scaffolding.c \
gtk_completion.c gtk_login.c gtk_throbber.c gtk_selection.c \
gtk_history.c gtk_window.c gtk_filetype.c gtk_download.c \
gtk_print.c gtk_tabs.c \
gtk_menu.c gtk_print.c gtk_save.c gtk_search.c gtk_tabs.c \
gtk_theme.c gtk_toolbar.c sexy_icon_entry.c \
$(addprefix dialogs/,gtk_options.c gtk_about.c gtk_source.c)
S_GTK := $(addprefix gtk/,$(S_GTK))
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
# code in utils/container.ch is non-universal it seems
# S_BEOS are sources purely for the BeOS build
S_BEOS := beos_about.cpp beos_bitmap.cpp beos_fetch_rsrc.cpp \
beos_filetype.cpp beos_font.cpp beos_gui.cpp beos_history.cpp \
beos_login.cpp beos_options.cpp beos_plotters.cpp \
beos_scaffolding.cpp beos_schedule.cpp beos_thumbnail.cpp \
beos_treeview.cpp beos_throbber.cpp beos_window.cpp
beos_scaffolding.cpp beos_search.cpp beos_schedule.cpp \
beos_thumbnail.cpp beos_treeview.cpp beos_throbber.cpp \
beos_window.cpp
S_BEOS := $(addprefix beos/,$(S_BEOS))
RDEF_BEOS := beos_res.rdef
RDEF_BEOS := $(addprefix beos/,$(RDEF_BEOS))

View File

@ -29,13 +29,13 @@
#include "amiga/download.h"
#include "amiga/object.h"
#include "amiga/options.h"
#include "amiga/save_complete.h"
#include "amiga/bitmap.h"
#include "amiga/iff_dr2d.h"
#include "content/fetch.h"
#include "desktop/selection.h"
#include "desktop/save_complete.h"
#include "utils/messages.h"
#include "utils/utils.h"

View File

@ -215,11 +215,11 @@ void ami_fetch_file_free(void *vf)
static void ami_fetch_file_send_callback(fetch_msg msg,
struct ami_file_fetch_info *fetch, const void *data,
unsigned long size)
unsigned long size, fetch_error_code errorcode)
{
fetch->locked = true;
/* LOG(("ami file fetcher callback %ld",msg)); */
fetch_send_callback(msg,fetch->fetch_handle,data,size);
fetch_send_callback(msg,fetch->fetch_handle,data,size,errorcode);
fetch->locked = false;
}
@ -234,6 +234,7 @@ void ami_fetch_file_poll(const char *scheme_ignored)
struct nsObject *node;
struct nsObject *nnode;
struct ami_file_fetch_info *fetch;
fetch_error_code errorcode;
if(IsMinListEmpty(ami_file_fetcher_list)) return;
@ -241,6 +242,7 @@ void ami_fetch_file_poll(const char *scheme_ignored)
do
{
errorcode = FETCH_ERROR_NO_ERROR;
nnode=(struct nsObject *)GetSucc((struct Node *)node);
fetch = (struct ami_file_fetch_info *)node->objstruct;
@ -255,13 +257,19 @@ void ami_fetch_file_poll(const char *scheme_ignored)
len = FRead(fetch->fh,ami_file_fetcher_buffer,1,1024);
ami_fetch_file_send_callback(FETCH_DATA,
fetch,ami_file_fetcher_buffer,len);
if (len == (ULONG)-1)
errorcode = FETCH_ERROR_MISC;
else if (len > 0)
ami_fetch_file_send_callback(
FETCH_DATA, fetch,
ami_file_fetcher_buffer,
len, errorcode);
if((len<1024) && (!fetch->aborted))
{
ami_fetch_file_send_callback(FETCH_FINISHED,
fetch, &fetch->cachedata, 0);
fetch, &fetch->cachedata, 0,
errorcode);
fetch->aborted = true;
}
@ -284,7 +292,8 @@ void ami_fetch_file_poll(const char *scheme_ignored)
LOG(("mimetype %s len %ld",fetch->mimetype,fetch->len));
ami_fetch_file_send_callback(FETCH_TYPE,
fetch, fetch->mimetype, (ULONG)fetch->len);
fetch, fetch->mimetype, (ULONG)fetch->len,
errorcode);
}
else
{
@ -292,8 +301,11 @@ void ami_fetch_file_poll(const char *scheme_ignored)
errorstring = ASPrintf("%s %s",messages_get("FileError"),fetch->path);
fetch_set_http_code(fetch->fetch_handle,404);
errorcode = FETCH_ERROR_HTTP_NOT2;
ami_fetch_file_send_callback(FETCH_ERROR, fetch,
errorstring, 0);
errorstring, 0,
errorcode);
fetch->aborted = true;
FreeVec(errorstring);
}

View File

@ -47,6 +47,7 @@
#include "amiga/menu.h"
#include "amiga/options.h"
#include <libraries/keymap.h>
#include "desktop/save_complete.h"
#include "desktop/textinput.h"
#include <intuition/pointerclass.h>
#include <math.h>
@ -66,7 +67,6 @@
#include "amiga/cookies.h"
#include "amiga/clipboard.h"
#include <proto/keymap.h>
#include "amiga/save_complete.h"
#include "amiga/fetch_file.h"
#include "amiga/fetch_mailto.h"
#include "amiga/search.h"
@ -3410,6 +3410,23 @@ void gui_window_stop_throbber(struct gui_window *g)
// g->shared->throbber_frame = 0;
}
/**
* function to add retrieved favicon to gui
*/
void gui_window_set_icon(struct gui_window *g, struct content *icon)
{
}
/**
* set gui display of a retrieved favicon representing the search
* provider
* \param ico may be NULL for local calls; then access current cache from
* search_web_ico()
*/
void gui_window_set_search_ico(struct content *ico)
{
}
void ami_update_throbber(struct gui_window_2 *g,bool redraw)
{
struct IBox *bbox;

View File

@ -56,6 +56,8 @@ enum
GID_NEXT,
GID_PREV,
GID_SEARCHSTRING,
GID_SHOWALL,
GID_CASE,
GID_HSCROLL,
GID_LAST
};

View File

@ -30,13 +30,13 @@
#include "amiga/save_pdf.h"
#include "desktop/save_text.h"
#include "desktop/save_pdf/pdf_plotters.h"
#include "desktop/save_complete.h"
#include <string.h>
#include "amiga/tree.h"
#include "amiga/history.h"
#include "amiga/cookies.h"
#include <proto/exec.h>
#include "amiga/arexx.h"
#include "amiga/save_complete.h"
#include "utils/url.h"
#include <dos/anchorpath.h>
#include "desktop/textinput.h"

View File

@ -2,6 +2,7 @@
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
* Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -18,807 +19,97 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Save HTML document with dependencies (implementation).
*/
#include "utils/config.h"
//#define _GNU_SOURCE /* for strndup */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
#include <libxml/HTMLtree.h>
#include <libxml/parserInternals.h>
#include "utils/config.h"
#include "css/css.h"
#include "render/box.h"
#include "amiga/save_complete.h"
#include "utils/log.h"
#include "utils/url.h"
#include "desktop/save_complete.h"
#include "utils/utils.h"
#include <proto/dos.h>
#include <proto/icon.h>
#include <workbench/icon.h>
regex_t save_complete_import_re;
/** An entry in save_complete_list. */
struct save_complete_entry {
struct content *content;
struct save_complete_entry *next; /**< Next entry in list */
};
/** List of urls seen and saved so far. */
static struct save_complete_entry *save_complete_list = 0;
static bool save_complete_html(struct content *c, const char *path,
bool index);
static bool save_imported_sheets(struct content *c, const char *path);
static char * rewrite_stylesheet_urls(const char *source, unsigned int size,
int *osize, const char *base);
static bool rewrite_document_urls(xmlDoc *doc, const char *base);
static bool rewrite_urls(xmlNode *n, const char *base);
static bool rewrite_url(xmlNode *n, const char *attr, const char *base);
static bool save_complete_list_add(struct content *content);
static struct content * save_complete_list_find(const char *url);
static bool save_complete_list_check(struct content *content);
/* static void save_complete_list_dump(void); */
static bool save_complete_inventory(const char *path);
#include "content/content.h"
/**
* Save an HTML page with all dependencies.
*
* \param c CONTENT_HTML to save
* \param path directory to save to (must exist)
* \return true on success, false on error and error reported
*/
* conducts the filesystem save appropriate to the gui
* \param path save path
* \param filename name of file to save
* \param len data length
* \param sourcedata pointer to data to save, NULL when all data in c
* \param type content type
* \return true for success
*/
bool save_complete(struct content *c, const char *path)
bool save_complete_gui_save(const char *path, const char *filename, size_t len,
const char *sourcedata, content_type type)
{
bool result;
result = save_complete_html(c, path, true);
if (result)
result = save_complete_inventory(path);
/* free save_complete_list */
while (save_complete_list) {
struct save_complete_entry *next = save_complete_list->next;
free(save_complete_list);
save_complete_list = next;
}
return result;
}
/**
* Save an HTML page with all dependencies, recursing through imported pages.
*
* \param c CONTENT_HTML to save
* \param path directory to save to (must exist)
* \param index true to save as "index"
* \return true on success, false on error and error reported
*/
bool save_complete_html(struct content *c, const char *path, bool index)
{
char spath[256];
unsigned int i;
htmlParserCtxtPtr parser;
BPTR fh = 0;
if (c->type != CONTENT_HTML)
return false;
if (save_complete_list_check(c))
return true;
/* save stylesheets, ignoring the base and adblocking sheets */
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++) {
struct content *css = c->data.html.stylesheets[i].c;
char *source;
int source_len;
bool is_style;
if (!css)
continue;
if (save_complete_list_check(css))
continue;
is_style = (strcmp(css->url, c->data.html.base_url) == 0);
if (is_style == false) {
if (!save_complete_list_add(css)) {
warn_user("NoMemory", 0);
return false;
}
}
if (!save_imported_sheets(css, path))
return false;
if (is_style)
continue; /* don't save <style> elements */
snprintf(spath, sizeof spath, "%s/%x", path,
(unsigned int) css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url);
if (!source) {
warn_user("NoMemory", 0);
return false;
}
/*
error = xosfile_save_stamped(spath, 0xf79, source,
source + source_len);
*/
if(fh = FOpen(spath,MODE_NEWFILE,0))
{
FWrite(fh,source,1,source_len);
FClose(fh);
SetComment(spath,c->url);
}
free(source);
/*
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
return false;
}
*/
}
/* save objects */
for (i = 0; i != c->data.html.object_count; i++) {
struct content *obj = c->data.html.object[i].content;
/* skip difficult content types */
if (!obj || obj->type >= CONTENT_OTHER || !obj->source_data)
continue;
if (save_complete_list_check(obj))
continue;
if (!save_complete_list_add(obj)) {
warn_user("NoMemory", 0);
return false;
}
if (obj->type == CONTENT_HTML) {
if (!save_complete_html(obj, path, false))
return false;
continue;
}
snprintf(spath, sizeof spath, "%s/%x", path,
(unsigned int) obj);
/*
error = xosfile_save_stamped(spath,
ro_content_filetype(obj),
obj->source_data,
obj->source_data + obj->source_size);
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
return false;
}
*/
if(fh = FOpen(spath,MODE_NEWFILE,0))
{
FWrite(fh,obj->source_data,1,obj->source_size);
FClose(fh);
SetComment(spath,obj->url);
}
}
/*save_complete_list_dump();*/
/* make a copy of the document tree */
parser = htmlCreateMemoryParserCtxt(c->source_data, c->source_size);
if (!parser) {
int res;
int namelen;
char deftype[5];
struct DiskObject *dobj = NULL;
namelen = strlen(path) + strlen(filename) + 2;
char *fullpath = malloc(namelen);
if (!fullpath) {
warn_user("NoMemory", 0);
return false;
}
/* set parser charset */
if (c->data.html.encoding) {
xmlCharEncodingHandler *enc_handler;
enc_handler =
xmlFindCharEncodingHandler(c->data.html.encoding);
if (enc_handler) {
xmlCtxtResetLastError(parser);
if (xmlSwitchToEncoding(parser, enc_handler)) {
xmlFreeDoc(parser->myDoc);
htmlFreeParserCtxt(parser);
warn_user("MiscError",
"Encoding switch failed");
return false;
}
}
}
htmlParseDocument(parser);
/* rewrite all urls we know about */
if (!rewrite_document_urls(parser->myDoc, c->data.html.base_url)) {
xmlFreeDoc(parser->myDoc);
htmlFreeParserCtxt(parser);
warn_user("NoMemory", 0);
snprintf(fullpath, namelen, "%s/%s", path, filename);
FILE *f = fopen(fullpath, "w");
if (f == NULL)
return false;
}
/* save the html file out last of all */
if (index)
res = fwrite(sourcedata, len, 1, f);
fclose(f);
switch(type)
{
struct DiskObject *dobj = NULL;
snprintf(spath, sizeof spath, "%s/index", path);
dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,"html",
ICONGETA_GetDefaultType,WBPROJECT,
TAG_DONE);
PutIconTags(spath,dobj,
ICONPUTA_NotifyWorkbench,TRUE,
TAG_DONE);
}
else
{
snprintf(spath, sizeof spath, "%s/%x", path, (unsigned int)c);
}
errno = 0;
if (htmlSaveFileFormat(spath, parser->myDoc, 0, 0) == -1) {
if (errno)
warn_user("SaveError", strerror(errno));
else
warn_user("SaveError", "htmlSaveFileFormat failed");
return false;
}
/*
error = xosfile_set_type(spath, 0xfaf);
if (error) {
LOG(("xosfile_set_type: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
return false;
}
*/
xmlFreeDoc(parser->myDoc);
htmlFreeParserCtxt(parser);
return true;
}
/**
* Save stylesheets imported by a CONTENT_CSS.
*
* \param c a CONTENT_CSS
* \param path path to save to
* \return true on success, false on error and error reported
*/
bool save_imported_sheets(struct content *c, const char *path)
{
char spath[256];
unsigned int j;
char *source;
int source_len;
BPTR fh = 0;
for (j = 0; j != c->data.css.import_count; j++) {
struct content *css = c->data.css.imports[j].c;
if (!css)
continue;
if (save_complete_list_check(css))
continue;
if (!save_complete_list_add(css)) {
warn_user("NoMemory", 0);
return false;
}
if (!save_imported_sheets(css, path))
return false;
snprintf(spath, sizeof spath, "%s/%x", path,
(unsigned int) css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url);
if (!source) {
warn_user("NoMemory", 0);
return false;
}
if(fh = FOpen(spath,MODE_NEWFILE,0))
{
FWrite(fh,source,1,source_len);
FClose(fh);
SetComment(spath,c->url);
}
/*
error = xosfile_save_stamped(spath, 0xf79, source,
source + source_len);
*/
free(source);
/*
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
return false;
}
*/
}
return true;
}
/**
* Initialise the save_complete module.
*/
void save_complete_init(void)
{
/* Match an @import rule - see CSS 2.1 G.1. */
regcomp_wrapper(&save_complete_import_re,
"@import" /* IMPORT_SYM */
"[ \t\r\n\f]*" /* S* */
/* 1 */
"(" /* [ */
/* 2 3 */
"\"(([^\"]|[\\]\")*)\"" /* STRING (approximated) */
"|"
/* 4 5 */
"'(([^']|[\\]')*)'"
"|" /* | */
"url\\([ \t\r\n\f]*" /* URI (approximated) */
/* 6 7 */
"\"(([^\"]|[\\]\")*)\""
"[ \t\r\n\f]*\\)"
"|"
"url\\([ \t\r\n\f]*"
/* 8 9 */
"'(([^']|[\\]')*)'"
"[ \t\r\n\f]*\\)"
"|"
"url\\([ \t\r\n\f]*"
/* 10 */
"([^) \t\r\n\f]*)"
"[ \t\r\n\f]*\\)"
")", /* ] */
REG_EXTENDED | REG_ICASE);
}
/**
* Rewrite stylesheet \@import rules for save complete.
*
* @param source stylesheet source
* @param size size of source
* @param osize updated with the size of the result
* @param base url of stylesheet
* @return converted source, or 0 on out of memory
*/
char * rewrite_stylesheet_urls(const char *source, unsigned int size,
int *osize, const char *base)
{
char *res;
const char *url;
char *url2;
char buf[20];
unsigned int offset = 0;
int url_len = 0;
struct content *content;
int m;
unsigned int i;
unsigned int imports = 0;
regmatch_t match[11];
url_func_result result;
/* count number occurences of @import to (over)estimate result size */
/* can't use strstr because source is not 0-terminated string */
for (i = 0; 7 < size && i != size - 7; i++) {
if (source[i] == '@' &&
tolower(source[i + 1]) == 'i' &&
tolower(source[i + 2]) == 'm' &&
tolower(source[i + 3]) == 'p' &&
tolower(source[i + 4]) == 'o' &&
tolower(source[i + 5]) == 'r' &&
tolower(source[i + 6]) == 't')
imports++;
}
res = malloc(size + imports * 20);
if (!res)
return 0;
*osize = 0;
while (offset < size) {
m = regexec(&save_complete_import_re, source + offset,
11, match, 0);
if (m)
case CONTENT_HTML:
strcpy(deftype,"html");
break;
/*for (unsigned int i = 0; i != 11; i++) {
if (match[i].rm_so == -1)
continue;
fprintf(stderr, "%i: '%.*s'\n", i,
match[i].rm_eo - match[i].rm_so,
source + offset + match[i].rm_so);
}*/
url = 0;
if (match[2].rm_so != -1) {
url = source + offset + match[2].rm_so;
url_len = match[2].rm_eo - match[2].rm_so;
} else if (match[4].rm_so != -1) {
url = source + offset + match[4].rm_so;
url_len = match[4].rm_eo - match[4].rm_so;
} else if (match[6].rm_so != -1) {
url = source + offset + match[6].rm_so;
url_len = match[6].rm_eo - match[6].rm_so;
} else if (match[8].rm_so != -1) {
url = source + offset + match[8].rm_so;
url_len = match[8].rm_eo - match[8].rm_so;
} else if (match[10].rm_so != -1) {
url = source + offset + match[10].rm_so;
url_len = match[10].rm_eo - match[10].rm_so;
}
assert(url);
url2 = strndup(url, url_len);
if (!url2) {
free(res);
return 0;
}
result = url_join(url2, base, (char**)&url);
free(url2);
if (result == URL_FUNC_NOMEM) {
free(res);
return 0;
}
/* copy data before match */
memcpy(res + *osize, source + offset, match[0].rm_so);
*osize += match[0].rm_so;
if (result == URL_FUNC_OK) {
content = save_complete_list_find(url);
if (content) {
/* replace import */
snprintf(buf, sizeof buf, "@import '%x'",
(unsigned int) content);
memcpy(res + *osize, buf, strlen(buf));
*osize += strlen(buf);
} else {
/* copy import */
memcpy(res + *osize, source + offset + match[0].rm_so,
match[0].rm_eo - match[0].rm_so);
*osize += match[0].rm_eo - match[0].rm_so;
}
}
else {
/* copy import */
memcpy(res + *osize, source + offset + match[0].rm_so,
match[0].rm_eo - match[0].rm_so);
*osize += match[0].rm_eo - match[0].rm_so;
}
assert(0 < match[0].rm_eo);
offset += match[0].rm_eo;
}
/* copy rest of source */
if (offset < size) {
memcpy(res + *osize, source + offset, size - offset);
*osize += size - offset;
}
return res;
}
/**
* Rewrite URLs in a HTML document to be relative.
*
* \param doc root of the document tree
* \param base base url of document
* \return true on success, false on out of memory
*/
bool rewrite_document_urls(xmlDoc *doc, const char *base)
{
xmlNode *node;
for (node = doc->children; node; node = node->next)
if (node->type == XML_ELEMENT_NODE)
if (!rewrite_urls(node, base))
return false;
return true;
}
/**
* Traverse tree, rewriting URLs as we go.
*
* \param n xmlNode of type XML_ELEMENT_NODE to rewrite
* \param base base url of document
* \return true on success, false on out of memory
*
* URLs in the tree rooted at element n are rewritten.
*/
bool rewrite_urls(xmlNode *n, const char *base)
{
xmlNode *child;
assert(n->type == XML_ELEMENT_NODE);
/**
* We only need to consider the following cases:
*
* Attribute: Elements:
*
* 1) data <object>
* 2) href <a> <area> <link>
* 3) src <script> <input> <frame> <iframe> <img>
* 4) n/a <style>
* 5) n/a any <base> tag
* 6) background any (except those above)
*/
if (!n->name) {
/* ignore */
}
/* 1 */
else if (strcmp(n->name, "object") == 0) {
if (!rewrite_url(n, "data", base))
case CONTENT_CSS:
strcpy(deftype,"css");
break;
default:
free(fullpath);
return false;
break;
}
/* 2 */
else if (strcmp(n->name, "a") == 0 ||
strcmp(n->name, "area") == 0 ||
strcmp(n->name, "link") == 0) {
if (!rewrite_url(n, "href", base))
return false;
}
/* 3 */
else if (strcmp(n->name, "frame") == 0 ||
strcmp(n->name, "iframe") == 0 ||
strcmp(n->name, "input") == 0 ||
strcmp(n->name, "img") == 0 ||
strcmp(n->name, "script") == 0) {
if (!rewrite_url(n, "src", base))
return false;
}
/* 4 */
else if (strcmp(n->name, "style") == 0) {
unsigned int len;
xmlChar *content;
for (child = n->children; child != 0; child = child->next) {
/* Get current content */
content = xmlNodeGetContent(child);
if (!content)
/* unfortunately we don't know if this is
* due to memory exhaustion, or because
* there is no content for this node */
continue;
/* Rewrite @import rules */
char *rewritten = rewrite_stylesheet_urls(
content,
strlen((char*)content),
&len, base);
xmlFree(content);
if (!rewritten)
return false;
/* set new content */
xmlNodeSetContentLen(child,
(const xmlChar*)rewritten,
len);
}
return true;
}
/* 5 */
else if (strcmp(n->name, "base") == 0) {
/* simply remove any <base> tags from the document */
xmlUnlinkNode(n);
xmlFreeNode(n);
/* base tags have no content, so there's no point recursing
* additionally, we've just destroyed this node, so trying
* to recurse would result in bad things happening */
return true;
}
/* 6 */
else {
if (!rewrite_url(n, "background", base))
return false;
}
/* now recurse */
for (child = n->children; child;) {
/* we must extract the next child now, as if the current
* child is a <base> element, it will be removed from the
* tree (see 5, above), thus preventing extraction of the
* next child */
xmlNode *next = child->next;
if (child->type == XML_ELEMENT_NODE) {
if (!rewrite_urls(child, base))
return false;
}
child = next;
}
dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,deftype,
ICONGETA_GetDefaultType,WBPROJECT,
TAG_DONE);
PutIconTags(fullpath, dobj,
ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
free(fullpath);
if (res != 1)
return false;
return true;
}
/**
* Rewrite an URL in a HTML document.
*
* \param n The node to modify
* \param attr The html attribute to modify
* \param base base url of document
* \return true on success, false on out of memory
*/
* wrapper for lib function htmlSaveFileFormat; front sets path from
* path + filename in a filesystem-specific way
*/
bool rewrite_url(xmlNode *n, const char *attr, const char *base)
int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
xmlDocPtr cur, const char *encoding, int format)
{
char *url, *data;
char rel[20];
struct content *content;
url_func_result res;
if (!xmlHasProp(n, (const xmlChar *) attr))
return true;
data = xmlGetProp(n, (const xmlChar *) attr);
if (!data)
return false;
res = url_join(data, base, &url);
xmlFree(data);
if (res == URL_FUNC_NOMEM)
return false;
else if (res == URL_FUNC_OK) {
content = save_complete_list_find(url);
if (content) {
/* found a match */
free(url);
snprintf(rel, sizeof rel, "%x",
(unsigned int) content);
if (!xmlSetProp(n, (const xmlChar *) attr,
(xmlChar *) rel))
return false;
} else {
/* no match found */
if (!xmlSetProp(n, (const xmlChar *) attr,
(xmlChar *) url)) {
free(url);
return false;
}
free(url);
}
int ret;
int len = strlen(path) + strlen(filename) + 2;
struct DiskObject *dobj = NULL;
char *fullpath = malloc(len);
if (!fullpath){
warn_user("NoMemory", 0);
return -1;
}
return true;
}
/**
* Add a content to the save_complete_list.
*
* \param content content to add
* \return true on success, false on out of memory
*/
bool save_complete_list_add(struct content *content)
{
struct save_complete_entry *entry;
entry = malloc(sizeof (*entry));
if (!entry)
return false;
entry->content = content;
entry->next = save_complete_list;
save_complete_list = entry;
return true;
}
/**
* Look up a url in the save_complete_list.
*
* \param url url to find
* \return content if found, 0 otherwise
*/
struct content * save_complete_list_find(const char *url)
{
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
if (strcmp(url, entry->content->url) == 0)
return entry->content;
return 0;
}
/**
* Look up a content in the save_complete_list.
*
* \param content pointer to content
* \return true if the content is in the save_complete_list
*/
bool save_complete_list_check(struct content *content)
{
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
if (entry->content == content)
return true;
return false;
}
#if 0
/**
* Dump save complete list to stderr
*/
void save_complete_list_dump(void)
{
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
fprintf(stderr, "%p : %s\n", entry->content,
entry->content->url);
}
#endif
/**
* Create the inventory file listing original URLs.
*/
bool save_complete_inventory(const char *path)
{
char spath[256];
FILE *fp;
snprintf(spath, sizeof spath, "%s/Inventory", path);
fp = fopen(spath, "w");
if (!fp) {
LOG(("fopen(): errno = %i", errno));
warn_user("SaveError", strerror(errno));
return false;
}
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
fprintf(fp, "%x %s\n",
(unsigned int) entry->content,
entry->content->url);
fclose(fp);
return true;
snprintf(fullpath, len, "%s/%s", path, filename);
ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
dobj = GetIconTags(NULL,ICONGETA_GetDefaultName, "html",
ICONGETA_GetDefaultType,WBPROJECT,
TAG_DONE);
PutIconTags(fullpath, dobj,
ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
free(fullpath);
return ret;
}

View File

@ -28,6 +28,7 @@
#include "content/content.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/search.h"
#include "desktop/selection.h"
#include "render/box.h"
#include "render/html.h"
@ -44,10 +45,12 @@
#include <proto/string.h>
#include <proto/button.h>
#include <proto/label.h>
#include <proto/checkbox.h>
#include <classes/window.h>
#include <gadgets/layout.h>
#include <gadgets/string.h>
#include <gadgets/button.h>
#include <gadgets/checkbox.h>
#include <images/label.h>
#include <reaction/reaction_macros.h>
@ -68,580 +71,25 @@ struct list_entry {
struct list_entry *next;
};
struct gui_window *search_current_window = NULL;
static bool search_insert;
static char *search_string = NULL;
static struct list_entry search_head = { 0, 0, NULL, NULL, NULL, NULL, NULL };
static struct list_entry *search_found = &search_head;
static struct list_entry *search_current = NULL;
static struct content *search_content = NULL;
static bool search_prev_case_sens = false;
static struct find_window *fwin = NULL;
#define RECENT_SEARCHES 8
bool search_insert;
static char *recent_search[RECENT_SEARCHES];
static void start_search(bool forwards,char *search_string);
static void do_search(char *string, int string_len, bool case_sens,
bool forwards);
static const char *find_pattern(const char *string, int s_len,
const char *pattern, int p_len, bool case_sens, int *m_len);
static bool find_occurrences_html(const char *pattern, int p_len,
struct box *cur, bool case_sens);
static bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens);
static struct list_entry *add_entry(unsigned start_idx, unsigned end_idx);
static void free_matches(void);
static void show_all(bool all);
static void show_status(bool found);
/**
* Begins/continues the search process
* Note that this may be called many times for a single search.
*
* \param forwards search forwards from start/current position
*/
void start_search(bool forwards,char *string)
{
int string_len;
int i = 0;
string_len = strlen(string);
for(i = 0; i < string_len; i++)
if (string[i] != '#' && string[i] != '*') break;
if (i >= string_len) {
free_matches();
show_status(true);
RefreshSetGadgetAttrs(fwin->gadgets[GID_PREV],fwin->win,NULL,
GA_Disabled,TRUE,
TAG_DONE);
RefreshSetGadgetAttrs(fwin->gadgets[GID_NEXT],fwin->win,NULL,
GA_Disabled,TRUE,
TAG_DONE);
gui_window_set_scroll(search_current_window, 0, 0);
return;
}
do_search(string, string_len,
false, // case sensitivity
forwards);
}
/**
* Ends the search process, invalidating all global state and
* freeing the list of found boxes
*
* \param w the search window handle (not used)
*/
void ami_gui_search_end(void)
{
search_current_window = 0;
if (search_string) {
//ro_gui_search_add_recent(search_string);
free(search_string);
}
search_string = 0;
free_matches();
search_current = 0;
search_content = 0;
search_prev_case_sens = false;
}
/**
* Release the memory used by the list of matches,
* deleting selection objects too
*/
void free_matches(void)
{
struct list_entry *a = search_found->next;
struct list_entry *b;
/* empty the list before clearing and deleting the
selections because the the clearing updates the
screen immediately, causing nested accesses to the list */
search_found->prev = 0;
search_found->next = 0;
for (; a; a = b) {
b = a->next;
if (a->sel) {
selection_clear(a->sel, true);
selection_destroy(a->sel);
}
free(a);
}
}
/**
* Search for a string in the box tree
*
* \param string the string to search for
* \param string_len length of search string
* \param case_sens whether to perform a case sensitive search
* \param forwards direction to search in
*/
void do_search(char *string, int string_len, bool case_sens, bool forwards)
{
struct rect bounds;
struct content *c;
struct box *box;
bool new = false;
if (!search_current_window)
return;
c = search_current_window->shared->bw->current_content;
/* only handle html contents */
if ((!c) || (c->type != CONTENT_HTML &&
c->type != CONTENT_TEXTPLAIN))
return;
box = c->data.html.layout;
if (!box)
return;
// LOG(("do_search '%s' - '%s' (%p, %p) %p (%d, %d) %d",
// search_string, string, search_content, c, search_found->next,
// search_prev_case_sens, case_sens, forwards));
/* check if we need to start a new search or continue an old one */
if (!search_string || c != search_content || !search_found->next ||
search_prev_case_sens != case_sens ||
(case_sens && strcmp(string, search_string) != 0) ||
(!case_sens && strcasecmp(string, search_string) != 0)) {
bool res;
if (search_string)
free(search_string);
search_current = 0;
free_matches();
search_string = malloc(string_len + 1);
if (search_string) {
memcpy(search_string, string, string_len);
search_string[string_len] = '\0';
}
// xhourglass_on();
if (c->type == CONTENT_HTML)
res = find_occurrences_html(string, string_len,
box, case_sens);
else {
assert(c->type == CONTENT_TEXTPLAIN);
res = find_occurrences_text(string, string_len,
c, case_sens);
}
if (!res) {
free_matches();
//xhourglass_off();
return;
}
//xhourglass_off();
new = true;
search_content = c;
search_prev_case_sens = case_sens;
}
// LOG(("%d %p %p (%p, %p)", new, search_found->next, search_current, search_current->prev, search_current->next));
if (new) {
/* new search, beginning at the top of the page */
search_current = search_found->next;
}
else if (search_current) {
/* continued search in the direction specified */
if (forwards) {
if (search_current->next)
search_current = search_current->next;
}
else {
if (search_current->prev)
search_current = search_current->prev;
}
}
show_status(search_current != NULL);
show_all(false);
RefreshSetGadgetAttrs(fwin->gadgets[GID_PREV],fwin->win,NULL,
GA_Disabled,(!search_current || !search_current->prev),
TAG_DONE);
RefreshSetGadgetAttrs(fwin->gadgets[GID_NEXT],fwin->win,NULL,
GA_Disabled,(!search_current || !search_current->next),
TAG_DONE);
if (!search_current)
return;
switch (c->type) {
case CONTENT_HTML:
/* get box position and jump to it */
box_coords(search_current->start_box,
&bounds.x0, &bounds.y0);
/* \todo: move x0 in by correct idx */
box_coords(search_current->end_box,
&bounds.x1, &bounds.y1);
/* \todo: move x1 in by correct idx */
bounds.x1 += search_current->end_box->width;
bounds.y1 += search_current->end_box->height;
break;
default:
assert(c->type == CONTENT_TEXTPLAIN);
textplain_coords_from_range(c,
search_current->start_idx,
search_current->end_idx, &bounds);
break;
}
gui_window_scroll_visible(search_current_window,
bounds.x0, bounds.y0, bounds.x1, bounds.y1);
}
/**
* Find the first occurrence of 'match' in 'string' and return its index
*
* /param string the string to be searched (unterminated)
* /param s_len length of the string to be searched
* /param pattern the pattern for which we are searching (unterminated)
* /param p_len length of pattern
* /param case_sens true iff case sensitive match required
* /param m_len accepts length of match in bytes
* /return pointer to first match, NULL if none
*/
const char *find_pattern(const char *string, int s_len, const char *pattern,
int p_len, bool case_sens, int *m_len)
{
struct { const char *ss, *s, *p; bool first; } context[16];
const char *ep = pattern + p_len;
const char *es = string + s_len;
const char *p = pattern - 1; /* a virtual '*' before the pattern */
const char *ss = string;
const char *s = string;
bool first = true;
int top = 0;
while (p < ep) {
bool matches;
if (p < pattern || *p == '*') {
char ch;
/* skip any further asterisks; one is the same as many */
do p++; while (p < ep && *p == '*');
/* if we're at the end of the pattern, yes, it matches */
if (p >= ep) break;
/* anything matches a # so continue matching from
here, and stack a context that will try to match
the wildcard against the next character */
ch = *p;
if (ch != '#') {
/* scan forwards until we find a match for this char */
if (!case_sens) ch = toupper(ch);
while (s < es) {
if (case_sens) {
if (*s == ch) break;
} else if (toupper(*s) == ch)
break;
s++;
}
}
if (s < es) {
/* remember where we are in case the match fails;
we can then resume */
if (top < (int)NOF_ELEMENTS(context)) {
context[top].ss = ss;
context[top].s = s + 1;
context[top].p = p - 1; /* ptr to last asterisk */
context[top].first = first;
top++;
}
if (first) {
ss = s; /* remember first non-'*' char */
first = false;
}
matches = true;
}
else
matches = false;
}
else if (s < es) {
char ch = *p;
if (ch == '#')
matches = true;
else {
if (case_sens)
matches = (*s == ch);
else
matches = (toupper(*s) == toupper(ch));
}
if (matches && first) {
ss = s; /* remember first non-'*' char */
first = false;
}
}
else
matches = false;
if (matches) {
p++; s++;
}
else {
/* doesn't match, resume with stacked context if we have one */
if (--top < 0) return NULL; /* no match, give up */
ss = context[top].ss;
s = context[top].s;
p = context[top].p;
first = context[top].first;
}
}
/* end of pattern reached */
*m_len = max(s - ss, 1);
return ss;
}
/**
* Finds all occurrences of a given string in the html box tree
*
* \param pattern the string pattern to search for
* \param p_len pattern length
* \param cur pointer to the current box
* \param case_sens whether to perform a case sensitive search
* \return true on success, false on memory allocation failure
*/
bool find_occurrences_html(const char *pattern, int p_len, struct box *cur,
bool case_sens)
{
struct box *a;
/* ignore this box, if there's no visible text */
if (!cur->object && cur->text) {
const char *text = cur->text;
unsigned length = cur->length;
while (length > 0) {
struct list_entry *entry;
unsigned match_length;
unsigned match_offset;
const char *new_text;
const char *pos = find_pattern(text, length,
pattern, p_len, case_sens,
&match_length);
if (!pos) break;
/* found string in box => add to list */
match_offset = pos - cur->text;
entry = add_entry(cur->byte_offset + match_offset,
cur->byte_offset +
match_offset +
match_length);
if (!entry)
return false;
entry->start_box = cur;
entry->end_box = cur;
new_text = pos + match_length;
length -= (new_text - text);
text = new_text;
}
}
/* and recurse */
for (a = cur->children; a; a = a->next) {
if (!find_occurrences_html(pattern, p_len, a, case_sens))
return false;
}
return true;
}
/**
* Finds all occurrences of a given string in a textplain content
*
* \param pattern the string pattern to search for
* \param p_len pattern length
* \param c the content to be searched
* \param case_sens wheteher to perform a case sensitive search
* \return true on success, false on memory allocation failure
*/
bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens)
{
int nlines = textplain_line_count(c);
int line;
for(line = 0; line < nlines; line++) {
size_t offset, length;
const char *text = textplain_get_line(c, line,
&offset, &length);
if (text) {
while (length > 0) {
struct list_entry *entry;
unsigned match_length;
size_t start_idx;
const char *new_text;
const char *pos = find_pattern(text, length,
pattern, p_len, case_sens,
&match_length);
if (!pos) break;
/* found string in line => add to list */
start_idx = offset + (pos - text);
entry = add_entry(start_idx, start_idx +
match_length);
if (!entry)
return false;
new_text = pos + match_length;
offset += (new_text - text);
length -= (new_text - text);
text = new_text;
}
}
}
return true;
}
/**
* Add a new entry to the list of matches
*
* \param start_idx offset of match start within textual representation
* \param end_idx offset of match end
* \return pointer to added entry, NULL iff failed
*/
struct list_entry *add_entry(unsigned start_idx, unsigned end_idx)
{
struct list_entry *entry;
/* found string in box => add to list */
entry = calloc(1, sizeof(*entry));
if (!entry) {
warn_user("NoMemory", 0);
return NULL;
}
entry->start_idx = start_idx;
entry->end_idx = end_idx;
entry->sel = NULL;
entry->next = 0;
entry->prev = search_found->prev;
if (!search_found->prev)
search_found->next = entry;
else
search_found->prev->next = entry;
search_found->prev = entry;
return entry;
}
/**
* Determines whether any portion of the given text box should be
* selected because it matches the current search string.
*
* \param g gui window
 * \param start_offset byte offset within text of string to be checked
* \param end_offset byte offset within text
* \param start_idx byte offset within string of highlight start
* \param end_idx byte offset of highlight end
* \return true iff part of the box should be highlighted
*/
bool gui_search_term_highlighted(struct gui_window *g,
unsigned start_offset, unsigned end_offset,
unsigned *start_idx, unsigned *end_idx)
{
if (g == search_current_window) {
struct list_entry *a;
for(a = search_found->next; a; a = a->next)
if (a->sel && selection_defined(a->sel) &&
selection_highlighted(a->sel,
start_offset, end_offset,
start_idx, end_idx))
return true;
}
return false;
}
/**
* Specifies whether all matches or just the current match should
* be highlighted in the search text.
*/
void show_all(bool all)
{
struct list_entry *a;
for (a = search_found->next; a; a = a->next) {
bool add = true;
if (!all && a != search_current) {
add = false;
if (a->sel) {
selection_clear(a->sel, true);
selection_destroy(a->sel);
a->sel = NULL;
}
}
if (add && !a->sel) {
a->sel = selection_create(search_current_window->shared->bw);
if (a->sel) {
struct content *c = search_current_window->shared->bw->current_content;
switch (c->type) {
case CONTENT_HTML:
selection_init(a->sel,
c->data.html.layout);
break;
default:
assert(c->type ==
CONTENT_TEXTPLAIN);
selection_init(a->sel, NULL);
break;
}
selection_set_start(a->sel, a->start_idx);
selection_set_end(a->sel, a->end_idx);
}
}
}
}
search_flags_t ami_search_flags(void);
char *ami_search_string(void);
static void ami_search_set_status(bool found, void *p);
static void ami_search_set_hourglass(bool active, void *p);
static void ami_search_add_recent(const char *string, void *p);
static void ami_search_set_forward_state(bool active, void *p);
static void ami_search_set_back_state(bool active, void *p);
static struct search_callbacks ami_search_callbacks = {
ami_search_set_forward_state,
ami_search_set_back_state,
ami_search_set_status,
ami_search_set_hourglass,
ami_search_add_recent
};
/**
@ -649,15 +97,6 @@ void show_all(bool all)
*
* \param found search pattern matched in text
*/
void show_status(bool found)
{
/*
ro_gui_set_icon_string(dialog_search, ICON_SEARCH_STATUS,
found ? "" : messages_get("NotFound"), true);
*/
}
void ami_search_open(struct gui_window *gwin)
{
struct content *c = gwin->shared->bw->current_content;
@ -667,12 +106,18 @@ void ami_search_open(struct gui_window *gwin)
c->type != CONTENT_TEXTPLAIN))
return;
search_current_window = gwin;
if (gwin->shared->bw->search_context == NULL)
search_create_context(gwin->shared->bw,
&ami_search_callbacks, NULL);
search_insert = true;
if(fwin)
{
ami_gui_search_end();
if(fwin->gwin->shared->bw->search_context != NULL)
search_destroy_context(fwin->gwin->shared->bw->
search_context);
ami_search_set_forward_state(true, NULL);
ami_search_set_back_state(true, NULL);
fwin->gwin->shared->searchwin = NULL;
fwin->gwin = gwin;
gwin->shared->searchwin = fwin;
@ -709,6 +154,21 @@ void ami_search_open(struct gui_window *gwin)
LabelEnd,
*/
CHILD_WeightedHeight,0,
LAYOUT_AddChild, fwin->gadgets[GID_CASE] = CheckBoxObject,
GA_ID,GID_CASE,
GA_Text,messages_get("CaseSens"),
GA_Selected,FALSE,
GA_TabCycle,TRUE,
GA_RelVerify,TRUE,
CheckBoxEnd,
LAYOUT_AddChild, fwin->gadgets[GID_SHOWALL] = CheckBoxObject,
GA_ID,GID_SHOWALL,
GA_Text,messages_get("ShowAll"),
GA_Selected,FALSE,
GA_TabCycle,TRUE,
GA_RelVerify,TRUE,
CheckBoxEnd,
LAYOUT_AddChild, HGroupObject,
LAYOUT_AddChild, fwin->gadgets[GID_PREV] = ButtonObject,
GA_ID,GID_PREV,
@ -739,7 +199,10 @@ void ami_search_open(struct gui_window *gwin)
void ami_search_close(void)
{
ami_gui_search_end();
if (fwin->gwin->shared->bw->search_context != NULL)
search_destroy_context(fwin->gwin->shared->bw->search_context);
ami_search_set_forward_state(true, NULL);
ami_search_set_back_state(true, NULL);
fwin->gwin->shared->searchwin = NULL;
DisposeObject(fwin->objects[OID_MAIN]);
DelObject(fwin->node);
@ -752,44 +215,158 @@ BOOL ami_search_event(void)
ULONG class,result,relevent = 0;
ULONG column;
uint16 code;
char *text;
search_flags_t flags;
while((result = RA_HandleInput(fwin->objects[OID_MAIN],&code)) != WMHI_LASTMSG)
{
switch(result & WMHI_CLASSMASK) // class
{
case WMHI_GADGETUP:
switch(result & WMHI_GADGETMASK)
{
case GID_NEXT:
search_insert = true;
GetAttr(STRINGA_TextVal,fwin->gadgets[GID_SEARCHSTRING],(ULONG *)&text);
start_search(true,text);
break;
case GID_PREV:
search_insert = true;
GetAttr(STRINGA_TextVal,fwin->gadgets[GID_SEARCHSTRING],(ULONG *)&text);
start_search(false,text);
break;
case GID_SEARCHSTRING:
RefreshSetGadgetAttrs(fwin->gadgets[GID_PREV],fwin->win,NULL,
GA_Disabled,FALSE,
TAG_DONE);
RefreshSetGadgetAttrs(fwin->gadgets[GID_NEXT],fwin->win,NULL,
GA_Disabled,FALSE,
TAG_DONE);
break;
}
{
case WMHI_GADGETUP:
switch(result & WMHI_GADGETMASK)
{
case GID_NEXT:
search_insert = true;
flags = SEARCH_FLAG_FORWARDS |
ami_search_flags();
if (search_verify_new(
search_data.search_window,
&ami_search_callbacks, NULL))
search_step(fwin->gwin->shared->bw,
flags,
ami_search_string());
break;
case WMHI_CLOSEWINDOW:
ami_search_close();
return TRUE;
case GID_PREV:
search_insert = true;
flags = ~SEARCH_FLAG_FORWARDS &
ami_search_flags();
if (search_verify_new(
search_data.search_window,
&ami_search_callbacks, NULL))
search_step(fwin->gwin->shared->bw,
flags,
ami_search_string());
break;
case GID_SEARCHSTRING:
if (fwin->gwin->shared->
bw->search_context
!= NULL)
search_destroy_context(
fwin->gwin->
shared->bw->
search_context);
ami_search_set_forward_state(
true, NULL);
ami_search_set_back_state(
true, NULL);
RefreshSetGadgetAttrs(fwin->gadgets[GID_PREV],fwin->win,NULL,
GA_Disabled,FALSE,
TAG_DONE);
RefreshSetGadgetAttrs(fwin->gadgets[GID_NEXT],fwin->win,NULL,
GA_Disabled,FALSE,
TAG_DONE);
break;
}
break;
case WMHI_CLOSEWINDOW:
ami_search_close();
return TRUE;
break;
}
}
return FALSE;
}
/**
* Change the displayed search status.
* \param found search pattern matched in text
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void ami_search_set_status(bool found, void *p)
{
}
/**
* display hourglass while searching
* \param active start/stop indicator
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void ami_search_set_hourglass(bool active, void *p)
{
SetWindowPointer(fwin->win,
WA_BusyPointer,active,
WA_PointerDelay,active,
TAG_DONE);
}
/**
* retrieve string being searched for from gui
*/
char *ami_search_string(void)
{
char *text;
GetAttr(STRINGA_TextVal,fwin->gadgets[GID_SEARCHSTRING],(ULONG *)&text);
return text;
}
/**
* add search string to recent searches list
* front is at liberty how to implement the bare notification
* should normally store a strdup() of the string;
* core gives no guarantee of the integrity of the const char *
* \param string search pattern
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void ami_search_add_recent(const char *string, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void ami_search_set_forward_state(bool active, void *p)
{
RefreshSetGadgetAttrs(fwin->gadgets[GID_NEXT],fwin->win,NULL,
GA_Disabled, active ? FALSE : TRUE, TAG_DONE);
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void ami_search_set_back_state(bool active, void *p)
{
RefreshSetGadgetAttrs(fwin->gadgets[GID_PREV],fwin->win,NULL,
GA_Disabled, active ? FALSE : TRUE, TAG_DONE);
}
/**
* retrieve state of 'case sensitive', 'show all' checks in gui
*/
search_flags_t ami_search_flags(void)
{
ULONG case_sensitive, showall;
search_flags_t flags;
GetAttr(GA_Selected,fwin->gadgets[GID_CASE],(ULONG *)&case_sensitive);
GetAttr(GA_Selected,fwin->gadgets[GID_SHOWALL],(ULONG *)&showall);
flags = 0 | (case_sensitive ? SEARCH_FLAG_CASE_SENSITIVE : 0) |
(showall ? SEARCH_FLAG_SHOWALL : 0);
return flags;
}

View File

@ -2311,6 +2311,22 @@ void gui_window_stop_throbber(struct gui_window* _g)
g->top_view->UnlockLooper();
}
/**
* add retrieved favicon to the gui
*/
void gui_window_set_icon(struct gui_window *g, struct content *icon)
{
}
/**
* set gui display of a retrieved favicon representing the search provider
* \param ico may be NULL for local calls; then access current cache from
* search_web_ico()
*/
void gui_window_set_search_ico(struct content *ico)
{
}
#warning XXX
#if 0 /* GTK */
gboolean nsbeos_scaffolding_is_busy(nsbeos_scaffolding *scaffold)

75
beos/beos_search.cpp Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <string.h>
extern "C" {
#include "utils/log.h"
}
/* callback functions for search implementation */
static void gui_search_set_status(bool found, void *p);
static void gui_search_set_hourglass(bool active, void *p);
static void gui_search_add_recent(const char *string, void *p);
static void gui_search_set_forward_state(bool active, void *p);
static void gui_search_set_back_state(bool active, void *p);
/**
* Change the displayed search status.
* \param found search pattern matched in text
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_status(bool found, void *p)
{
}
/**
* display hourglass while searching
* \param active start/stop indicator
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_hourglass(bool active, void *p)
{
}
/**
* add search string to recent searches list
* \param string search pattern
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_add_recent(const char *string, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_forward_state(bool active, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_back_state(bool active, void *p)
{
}

View File

@ -155,6 +155,9 @@ static const struct mime_entry mime_map[] = {
{"image/svg", CONTENT_SVG},
{"image/svg+xml", CONTENT_SVG},
#endif
#ifdef WITH_BMP
{"image/vnd.microsoft.icon", CONTENT_ICO},
#endif
#ifdef WITH_ARTWORKS
{"image/x-artworks", CONTENT_ARTWORKS},
#endif

View File

@ -601,11 +601,11 @@ bool fetch_get_verifiable(struct fetch *fetch)
void
fetch_send_callback(fetch_msg msg, struct fetch *fetch, const void *data,
unsigned long size)
unsigned long size, fetch_error_code errorcode)
{
/*LOG(("Fetcher sending callback. Fetch %p, fetcher %p data %p size %lu",
fetch, fetch->fetcher_handle, data, size)); */
fetch->callback(msg, fetch->p, data, size);
fetch->callback(msg, fetch->p, data, size, errorcode);
}

View File

@ -40,6 +40,19 @@ typedef enum {
FETCH_CERT_ERR,
} fetch_msg;
typedef enum {
FETCH_ERROR_NO_ERROR,
FETCH_ERROR_CERT,
FETCH_ERROR_AUTHENTICATION,
FETCH_ERROR_HTTP_NOT2,
FETCH_ERROR_COULDNT_RESOLVE_HOST,
FETCH_ERROR_PARTIAL_FILE,
FETCH_ERROR_MEMORY,
FETCH_ERROR_URL,
FETCH_ERROR_ENCODING,
FETCH_ERROR_MISC
} fetch_error_code;
struct content;
struct fetch;
struct form_successful_control;
@ -58,7 +71,7 @@ struct ssl_cert_info {
extern bool fetch_active;
typedef void (*fetch_callback)(fetch_msg msg, void *p, const void *data,
unsigned long size);
unsigned long size, fetch_error_code errorcode);
void fetch_init(void);
@ -105,7 +118,8 @@ bool fetch_add_fetcher(const char *scheme,
fetcher_finalise finaliser);
void fetch_send_callback(fetch_msg msg, struct fetch *fetch,
const void *data, unsigned long size);
const void *data, unsigned long size,
fetch_error_code errorcode);
void fetch_remove_from_queues(struct fetch *fetch);
void fetch_free(struct fetch *f);
void fetch_set_http_code(struct fetch *fetch, long http_code);

View File

@ -38,6 +38,8 @@
#include "content/content.h"
#include "content/fetchcache.h"
#include "content/fetch.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
#include "content/urldb.h"
#include "utils/log.h"
#include "utils/messages.h"
@ -49,17 +51,23 @@
static char error_page[1000];
static regex_t re_content_type;
static void fetchcache_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
unsigned long size, fetch_error_code errorcode);
static char *fetchcache_parse_type(const char *s, char **params[]);
static void fetchcache_parse_header(struct content *c, const char *data,
size_t size);
static void fetchcache_error_page(struct content *c, const char *error);
static void fetchcache_error_page(struct content *c, const char *error,
fetch_error_code errorcode);
static void fetchcache_search_redirect(struct content *c, const char *error);
static void fetchcache_cache_update(struct content *c);
static void fetchcache_cache_clone(struct content *c,
const struct cache_data *data);
static void fetchcache_notmodified(struct content *c, const void *data);
static void fetchcache_redirect(struct content *c, const void *data,
unsigned long size);
static void fetchcache_redirect_common(struct content *c, bool verifiable,
const char *url, const char *referer,
struct content *parent);
static void fetchcache_auth(struct content *c, const char *realm);
@ -276,7 +284,8 @@ void fetchcache_go(struct content *content, const char *referer,
callback(CONTENT_MSG_ERROR,
content, p1, p2, msg_data);
} else {
fetchcache_error_page(content, error_message);
fetchcache_error_page(content, error_message,
FETCH_ERROR_NO_ERROR);
}
return;
@ -366,7 +375,8 @@ void fetchcache_go(struct content *content, const char *referer,
content_broadcast(content, CONTENT_MSG_ERROR,
msg_data);
} else {
fetchcache_error_page(content, error_message);
fetchcache_error_page(content, error_message,
FETCH_ERROR_NO_ERROR);
}
}
@ -405,7 +415,7 @@ void fetchcache_go(struct content *content, const char *referer,
*/
void fetchcache_callback(fetch_msg msg, void *p, const void *data,
unsigned long size)
unsigned long size, fetch_error_code errorcode)
{
bool res;
struct content *c = p;
@ -506,7 +516,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const void *data,
msg_data);
} else {
content_reset(c);
fetchcache_error_page(c, data);
fetchcache_error_page(c, data, errorcode);
}
break;
@ -721,17 +731,29 @@ void fetchcache_parse_header(struct content *c, const char *data,
/**
* Generate an error page.
*
* Generate an error page. Optionally redirect to web search provider
* \param c empty content to generate the page in
* \param error message to display
*/
void fetchcache_error_page(struct content *c, const char *error)
void fetchcache_error_page(struct content *c, const char *error,
fetch_error_code errorcode)
{
const char *params[] = { 0 };
int length;
char *host;
if (option_search_url_bar) {
if (url_host(c->url, &host) != URL_FUNC_OK) {
warn_user(messages_get("NoMemory"), 0);
} else if ((strcasecmp(host, search_web_provider_host())
!= 0) && (errorcode ==
FETCH_ERROR_COULDNT_RESOLVE_HOST)) {
fetchcache_search_redirect(c, error);
free(host);
return;
}
}
if ((length = snprintf(error_page, sizeof(error_page),
messages_get("ErrorPage"), error)) < 0)
length = 0;
@ -746,6 +768,27 @@ void fetchcache_error_page(struct content *c, const char *error)
c->fresh = false;
}
void fetchcache_search_redirect(struct content *c, const char *error)
{
char *redirurl, *temp;
/* clear http:// plus trailing / from url, it is already escaped */
temp = strdup(c->url + SLEN("http://"));
if (temp == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
temp[strlen(temp)-1] = '\0';
redirurl = search_web_get_url(temp);
if (redirurl == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
fetchcache_redirect_common(c, false, redirurl, NULL, c);
free(redirurl);
return;
}
/**
* Update a content's cache state
@ -930,7 +973,6 @@ void fetchcache_redirect(struct content *c, const void *data,
long http_code;
const char *ref;
struct content *parent;
bool can_fetch;
bool parent_was_verifiable;
union content_msg_data msg_data;
url_func_result result;
@ -1056,32 +1098,50 @@ void fetchcache_redirect(struct content *c, const void *data,
}
free(scheme);
/* Determine if we've got a fetch handler for this url */
can_fetch = fetch_can_fetch(url);
fetchcache_redirect_common(c, parent_was_verifiable, url, referer, parent);
free(url);
free(referer);
}
/**
* common logic from fetchcache_redirect() / fetchcache_search_redirect()
* \param c the content param from the original function
* \param verifiable parent_was_verifiable [false for search_redirect]
* \param url the url being considered; caller retains ownership
* \param referer referer [ / NULL particularly for search_redirect]
* \param parent parent content [ / c for search_redirect]
*/
void fetchcache_redirect_common(struct content *c, bool verifiable,
const char *url, const char *referer, struct content *parent)
{
union content_msg_data msg_data;
bool can_fetch;
/* check there's a fetch handler */
can_fetch = fetch_can_fetch(url);
/* Process users of this content */
while (c->user_list->next) {
intptr_t p1, p2;
void (*callback)(content_msg msg,
struct content *c, intptr_t p1,
intptr_t p2,
union content_msg_data data);
struct content *c, intptr_t p1,
intptr_t p2,
union content_msg_data data);
struct content *replacement;
p1 = c->user_list->next->p1;
p2 = c->user_list->next->p2;
callback = c->user_list->next->callback;
/* If we can't fetch this url, attempt to launch it */
if (!can_fetch) {
msg_data.launch_url = url;
callback(CONTENT_MSG_LAUNCH, c, p1, p2, msg_data);
}
/* Remove user */
content_remove_user(c, callback, p1, p2);
if (can_fetch) {
/* Get replacement content -- HTTP GET request */
@ -1101,37 +1161,29 @@ void fetchcache_redirect(struct content *c, const void *data,
*/
replacement = fetchcache(url, callback, p1, p2,
c->width, c->height, c->no_error_pages,
NULL, NULL, parent_was_verifiable,
NULL, NULL, verifiable,
c->download);
if (!replacement) {
msg_data.error = messages_get("BadRedirect");
content_broadcast(c, CONTENT_MSG_ERROR,
msg_data);
free(url);
free(referer);
return;
}
}
/* Set replacement's redirect count to 1 greater
* than ours */
replacement->redirect_count = c->redirect_count + 1;
/* Notify user that content has changed */
msg_data.new_url = url;
callback(CONTENT_MSG_NEWPTR, replacement,
p1, p2, msg_data);
p1, p2, msg_data);
/* Start fetching the replacement content */
fetchcache_go(replacement, referer, callback, p1, p2,
c->width, c->height, NULL, NULL,
parent_was_verifiable, parent);
c->width, c->height, NULL, NULL,
verifiable, parent);
}
}
/* Clean up */
free(url);
free(referer);
}
/**
@ -1218,7 +1270,8 @@ void fetchcache_auth(struct content *c, const char *realm)
msg_data.error = error_message;
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
} else {
fetchcache_error_page(c, error_message);
fetchcache_error_page(c, error_message,
FETCH_ERROR_URL);
}
}

View File

@ -748,6 +748,7 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
{
bool finished = false;
bool error = false;
fetch_error_code errorcode = FETCH_ERROR_NO_ERROR;
bool cert = false;
bool abort_fetch;
struct curl_fetch_info *f;
@ -778,8 +779,10 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
* Content-Length header. */
if (!f->had_headers && fetch_curl_process_headers(f))
; /* redirect with partial body, or similar */
else
else {
error = true;
errorcode = FETCH_ERROR_PARTIAL_FILE;
}
} else if (result == CURLE_WRITE_ERROR && f->stopped)
/* CURLE_WRITE_ERROR occurs when fetch_curl_data
* returns 0, which we use to abort intentionally */
@ -790,9 +793,14 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
memset(f->cert_data, 0, sizeof(f->cert_data));
cert = true;
}
else if (result == CURLE_COULDNT_RESOLVE_HOST) {
error = true;
errorcode = FETCH_ERROR_COULDNT_RESOLVE_HOST;
}
else {
LOG(("Unknown cURL response code %d", result));
error = true;
errorcode = FETCH_ERROR_MISC;
}
fetch_curl_stop(f);
@ -800,7 +808,7 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
if (abort_fetch)
; /* fetch was aborted: no callback */
else if (finished)
fetch_send_callback(FETCH_FINISHED, f->fetch_handle, 0, 0);
fetch_send_callback(FETCH_FINISHED, f->fetch_handle, 0, 0, errorcode);
else if (cert) {
int i;
BIO *mem;
@ -877,14 +885,14 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
if (certs[i].cert->references == 0)
X509_free(certs[i].cert);
}
errorcode = FETCH_ERROR_CERT;
fetch_send_callback(FETCH_CERT_ERR, f->fetch_handle,
&ssl_certs, i);
&ssl_certs, i, errorcode);
}
else if (error)
fetch_send_callback(FETCH_ERROR, f->fetch_handle,
fetch_error_buffer, 0);
fetch_error_buffer, 0, errorcode);
fetch_free(f->fetch_handle);
}
@ -910,14 +918,16 @@ int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
human_friendly_bytesize(dlnow),
human_friendly_bytesize(dltotal));
fetch_send_callback(FETCH_PROGRESS, f->fetch_handle,
fetch_progress_buffer,
(unsigned long) percent);
fetch_progress_buffer,
(unsigned long) percent,
FETCH_ERROR_NO_ERROR);
} else {
snprintf(fetch_progress_buffer, 255,
messages_get("ProgressU"),
human_friendly_bytesize(dlnow));
fetch_send_callback(FETCH_PROGRESS, f->fetch_handle,
fetch_progress_buffer, 0);
fetch_progress_buffer, 0,
FETCH_ERROR_NO_ERROR);
}
return 0;
@ -977,7 +987,8 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
/* send data to the caller */
/*LOG(("FETCH_DATA"));*/
fetch_send_callback(FETCH_DATA, f->fetch_handle, data, size * nmemb);
fetch_send_callback(FETCH_DATA, f->fetch_handle, data, size * nmemb,
FETCH_ERROR_NO_ERROR);
if (f->abort) {
f->stopped = true;
@ -1006,7 +1017,8 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
return 0;
}
fetch_send_callback(FETCH_HEADER, f->fetch_handle, data, size);
fetch_send_callback(FETCH_HEADER, f->fetch_handle, data, size,
FETCH_ERROR_NO_ERROR);
#define SKIP_ST(o) for (i = (o); i < (int) size && (data[i] == ' ' || data[i] == '\t'); i++)
@ -1100,20 +1112,23 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
/* Not Modified && GET request */
fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle, 0, 0);
fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle, 0, 0,
FETCH_ERROR_NO_ERROR);
return true;
}
/* handle HTTP redirects (3xx response codes) */
if (300 <= http_code && http_code < 400 && f->location != 0) {
LOG(("FETCH_REDIRECT, '%s'", f->location));
fetch_send_callback(FETCH_REDIRECT, f->fetch_handle, f->location, 0);
fetch_send_callback(FETCH_REDIRECT, f->fetch_handle,
f->location, 0, FETCH_ERROR_NO_ERROR);
return true;
}
/* handle HTTP 401 (Authentication errors) */
if (http_code == 401) {
fetch_send_callback(FETCH_AUTH, f->fetch_handle, f->realm,0);
fetch_send_callback(FETCH_AUTH, f->fetch_handle, f->realm,0,
FETCH_ERROR_AUTHENTICATION);
return true;
}
@ -1121,7 +1136,8 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
if (f->only_2xx && strncmp(f->url, "http", 4) == 0 &&
(http_code < 200 || 299 < http_code)) {
fetch_send_callback(FETCH_ERROR, f->fetch_handle,
messages_get("Not2xx"), 0);
messages_get("Not2xx"), 0,
FETCH_ERROR_HTTP_NOT2);
return true;
}
@ -1141,7 +1157,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
"ETag: \"%10d\"", (int) s.st_mtime);
/* And send it to the header handler */
fetch_send_callback(FETCH_HEADER, f->fetch_handle, etag_buf,
strlen(etag_buf));
strlen(etag_buf), FETCH_ERROR_NO_ERROR);
/* don't set last modified time so as to ensure that local
* files are revalidated at all times. */
@ -1151,7 +1167,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
f->last_modified > s.st_mtime &&
f->file_etag == s.st_mtime) {
fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle,
0, 0);
0, 0, FETCH_ERROR_NO_ERROR);
curl_free(url_path);
return true;
}
@ -1167,7 +1183,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
curl_free(url_path);
LOG(("FETCH_TYPE, '%s'", type));
fetch_send_callback(FETCH_TYPE, f->fetch_handle, type, f->content_length);
fetch_send_callback(FETCH_TYPE, f->fetch_handle, type, f->content_length, FETCH_ERROR_NO_ERROR);
if (f->abort)
return true;

View File

@ -129,10 +129,10 @@ static void fetch_data_abort(void *ctx)
static void fetch_data_send_callback(fetch_msg msg,
struct fetch_data_context *c, const void *data,
unsigned long size)
unsigned long size, fetch_error_code errorcode)
{
c->locked = true;
fetch_send_callback(msg, c->parent_fetch, data, size);
fetch_send_callback(msg, c->parent_fetch, data, size, errorcode);
c->locked = false;
}
@ -154,7 +154,7 @@ static bool fetch_data_process(struct fetch_data_context *c)
if (strlen(c->url) < 6) {
/* 6 is the minimum possible length (data:,) */
fetch_data_send_callback(FETCH_ERROR, c,
"Malformed data: URL", 0);
"Malformed data: URL", 0, FETCH_ERROR_URL);
return false;
}
@ -164,7 +164,7 @@ static bool fetch_data_process(struct fetch_data_context *c)
/* find the comma */
if ( (comma = strchr(params, ',')) == NULL) {
fetch_data_send_callback(FETCH_ERROR, c,
"Malformed data: URL", 0);
"Malformed data: URL", 0, FETCH_ERROR_URL);
return false;
}
@ -179,7 +179,7 @@ static bool fetch_data_process(struct fetch_data_context *c)
if (c->mimetype == NULL) {
fetch_data_send_callback(FETCH_ERROR, c,
"Unable to allocate memory for mimetype in data: URL",
0);
0, FETCH_ERROR_MEMORY);
return false;
}
@ -198,7 +198,8 @@ static bool fetch_data_process(struct fetch_data_context *c)
c->datalen = templen;
if (unescaped == NULL) {
fetch_data_send_callback(FETCH_ERROR, c,
"Unable to URL decode data: URL", 0);
"Unable to URL decode data: URL", 0,
FETCH_ERROR_ENCODING);
return false;
}
@ -207,7 +208,8 @@ static bool fetch_data_process(struct fetch_data_context *c)
if (base64_decode(unescaped, c->datalen, c->data,
&(c->datalen)) == false) {
fetch_data_send_callback(FETCH_ERROR, c,
"Unable to Base64 decode data: URL", 0);
"Unable to Base64 decode data: URL", 0,
FETCH_ERROR_ENCODING);
curl_free(unescaped);
return false;
}
@ -215,7 +217,8 @@ static bool fetch_data_process(struct fetch_data_context *c)
c->data = malloc(c->datalen);
if (c->data == NULL) {
fetch_data_send_callback(FETCH_ERROR, c,
"Unable to allocate memory for data: URL", 0);
"Unable to allocate memory for data: URL", 0,
FETCH_ERROR_MEMORY);
curl_free(unescaped);
return false;
}
@ -271,14 +274,17 @@ static void fetch_data_poll(const char *scheme)
* call to fetch_data_send_callback().
*/
fetch_data_send_callback(FETCH_TYPE,
c, c->mimetype, c->datalen);
c, c->mimetype, c->datalen,
FETCH_ERROR_NO_ERROR);
if (!c->aborted) {
fetch_data_send_callback(FETCH_DATA,
c, c->data, c->datalen);
c, c->data, c->datalen,
FETCH_ERROR_NO_ERROR);
}
if (!c->aborted) {
fetch_data_send_callback(FETCH_FINISHED,
c, &cachedata, 0);
c, &cachedata, 0,
FETCH_ERROR_NO_ERROR);
}
} else {
LOG(("Processing of %s failed!", c->url));

View File

@ -87,12 +87,13 @@ static bool browser_window_check_throbber(struct browser_window *bw);
static void browser_window_convert_to_download(struct browser_window *bw);
static void browser_window_start_throbber(struct browser_window *bw);
static void browser_window_stop_throbber(struct browser_window *bw);
static void browser_window_set_icon(struct browser_window *bw);
static void browser_window_set_status(struct browser_window *bw,
const char *text);
static void browser_window_set_pointer(struct gui_window *g,
gui_pointer_shape shape);
static void download_window_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
unsigned long size, fetch_error_code errorcode);
static void browser_window_destroy_children(struct browser_window *bw);
static void browser_window_destroy_internal(struct browser_window *bw);
static void browser_window_set_scale_internal(struct browser_window *bw,
@ -167,6 +168,7 @@ struct browser_window *browser_window_create(const char *url,
if (url)
browser_window_go(bw, url, referer, history_add);
return bw;
}
@ -418,8 +420,6 @@ void browser_window_callback(content_msg msg, struct content *c,
}
#endif
else {
browser_window_refresh_url_bar(bw, c->url, bw->frag_id);
bw->refresh_interval = -1;
browser_window_set_status(bw, c->status_message);
}
@ -491,6 +491,7 @@ void browser_window_callback(content_msg msg, struct content *c,
browser_window_update(bw, false);
browser_window_set_status(bw, c->status_message);
browser_window_stop_throbber(bw);
browser_window_set_icon(bw);
history_update(bw->history, c);
hotlist_visited(c);
free(bw->referer);
@ -764,6 +765,21 @@ bool browser_window_check_throbber(struct browser_window *bw)
return false;
}
/**
* when ready, set icon at top level
* \param bw browser_window
* current implementation ignores lower-levels' link rels completely
*/
void browser_window_set_icon(struct browser_window *bw)
{
while (bw->parent)
bw = bw->parent;
if ((bw->current_content != NULL) && (bw->current_content->type == CONTENT_HTML))
gui_window_set_icon(bw->window,
bw->current_content->data.html.favicon);
else
gui_window_set_icon(bw->window, NULL);
}
/**
* Redraw browser window, set extent to content, and update title.
@ -1298,7 +1314,7 @@ void browser_window_find_target_internal(struct browser_window *bw,
*/
void download_window_callback(fetch_msg msg, void *p, const void *data,
unsigned long size)
unsigned long size, fetch_error_code errorcode)
{
struct gui_download_window *download_window = p;

View File

@ -170,6 +170,9 @@ struct browser_window {
/** Last time a link was followed in this window */
unsigned int last_action;
/** search context for free text search */
struct search_context *search_context;
struct form_control *visible_select_menu;
};

View File

@ -56,8 +56,7 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
#include "utils/config.h"
#include "content/content.h"
#include "desktop/browser.h"
extern struct gui_window *search_current_window;
#include "desktop/search.h"
void gui_init(int argc, char** argv);
void gui_init2(int argc, char** argv);
@ -67,6 +66,7 @@ void gui_quit(void);
struct gui_window *gui_create_browser_window(struct browser_window *bw,
struct browser_window *clone, bool new_tab);
struct browser_window *gui_window_get_browser_window(struct gui_window *g);
void gui_window_destroy(struct gui_window *g);
void gui_window_set_title(struct gui_window *g, const char *title);
void gui_window_redraw(struct gui_window *g, int x0, int y0, int x1, int y1);
@ -88,6 +88,8 @@ void gui_window_hide_pointer(struct gui_window *g);
void gui_window_set_url(struct gui_window *g, const char *url);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
void gui_window_set_icon(struct gui_window *g, struct content *icon);
void gui_window_set_search_ico(struct content *ico);
void gui_window_place_caret(struct gui_window *g, int x, int y, int height);
void gui_window_remove_caret(struct gui_window *g);
void gui_window_new_content(struct gui_window *g);
@ -125,7 +127,8 @@ void gui_launch_url(const char *url);
bool gui_search_term_highlighted(struct gui_window *g,
unsigned start_offset, unsigned end_offset,
unsigned *start_idx, unsigned *end_idx);
unsigned *start_idx, unsigned *end_idx,
struct search_context *context);
struct ssl_cert_info;

View File

@ -111,12 +111,16 @@ char *option_ca_bundle = 0;
char *option_ca_path = 0;
/** Cookie file location */
char *option_cookie_file = 0;
/** Cookie jar loaction */
/** Cookie jar location */
char *option_cookie_jar = 0;
/** Home page location */
char *option_homepage_url = 0;
/** search web from url bar */
bool option_search_url_bar = false;
/** URL completion in url bar */
bool option_url_suggestion = true;
/** default web search provider */
int option_search_provider = 0;
/** default x position of new windows */
int option_window_x = 0;
/** default y position of new windows */
@ -231,6 +235,8 @@ struct {
{ "cookie_file", OPTION_STRING, &option_cookie_file },
{ "cookie_jar", OPTION_STRING, &option_cookie_jar },
{ "homepage_url", OPTION_STRING, &option_homepage_url },
{ "search_url_bar", OPTION_BOOL, &option_search_url_bar},
{ "search_provider", OPTION_INTEGER, &option_search_provider},
{ "url_suggestion", OPTION_BOOL, &option_url_suggestion },
{ "window_x", OPTION_INTEGER, &option_window_x },
{ "window_y", OPTION_INTEGER, &option_window_y },

View File

@ -70,6 +70,8 @@ extern char *option_ca_path;
extern char *option_cookie_file;
extern char *option_cookie_jar;
extern char *option_homepage_url;
extern bool option_search_url_bar;
extern int option_search_provider;
extern bool option_target_blank;
extern bool option_button_2_tab;
extern bool option_url_suggestion;

View File

@ -33,13 +33,11 @@
#include <regex.h>
#include <libxml/HTMLtree.h>
#include <libxml/parserInternals.h>
#include "oslib/osfile.h"
#include "utils/config.h"
#include "content/content.h"
#include "css/css.h"
#include "render/box.h"
#include "riscos/gui.h"
#include "riscos/save_complete.h"
#include "desktop/save_complete.h"
#include "utils/log.h"
#include "utils/url.h"
#include "utils/utils.h"
@ -52,22 +50,28 @@ struct save_complete_entry {
struct save_complete_entry *next; /**< Next entry in list */
};
/** List of urls seen and saved so far. */
static struct save_complete_entry *save_complete_list = 0;
static bool save_complete_html(struct content *c, const char *path,
bool index);
static bool save_imported_sheets(struct content *c, const char *path);
bool index, struct save_complete_entry **list);
static bool save_imported_sheets(struct content *c, const char *path,
struct save_complete_entry **list);
static char * rewrite_stylesheet_urls(const char *source, unsigned int size,
int *osize, const char *base);
static bool rewrite_document_urls(xmlDoc *doc, const char *base);
static bool rewrite_urls(xmlNode *n, const char *base);
static bool rewrite_url(xmlNode *n, const char *attr, const char *base);
static bool save_complete_list_add(struct content *content);
static struct content * save_complete_list_find(const char *url);
static bool save_complete_list_check(struct content *content);
int *osize, const char *base,
struct save_complete_entry *list);
static bool rewrite_document_urls(xmlDoc *doc, const char *base,
struct save_complete_entry *list);
static bool rewrite_urls(xmlNode *n, const char *base,
struct save_complete_entry *list);
static bool rewrite_url(xmlNode *n, const char *attr, const char *base,
struct save_complete_entry *list);
static bool save_complete_list_add(struct content *content,
struct save_complete_entry **list);
static struct content * save_complete_list_find(const char *url,
struct save_complete_entry *list);
static bool save_complete_list_check(struct content *content,
struct save_complete_entry *list);
/* static void save_complete_list_dump(void); */
static bool save_complete_inventory(const char *path);
static bool save_complete_inventory(const char *path,
struct save_complete_entry *list);
/**
* Save an HTML page with all dependencies.
@ -80,17 +84,18 @@ static bool save_complete_inventory(const char *path);
bool save_complete(struct content *c, const char *path)
{
bool result;
result = save_complete_html(c, path, true);
struct save_complete_entry *list = NULL;
result = save_complete_html(c, path, true, &list);
if (result)
result = save_complete_inventory(path);
result = save_complete_inventory(path, list);
/* free save_complete_list */
while (save_complete_list) {
struct save_complete_entry *next = save_complete_list->next;
free(save_complete_list);
save_complete_list = next;
while (list) {
struct save_complete_entry *next = list->next;
free(list);
list = next;
}
return result;
@ -106,19 +111,20 @@ bool save_complete(struct content *c, const char *path)
* \return true on success, false on error and error reported
*/
bool save_complete_html(struct content *c, const char *path, bool index)
bool save_complete_html(struct content *c, const char *path, bool index,
struct save_complete_entry **list)
{
char spath[256];
char filename[256];
unsigned int i;
xmlDocPtr doc;
os_error *error;
bool res;
if (c->type != CONTENT_HTML)
return false;
if (save_complete_list_check(c))
if (save_complete_list_check(c, *list))
return true;
/* save stylesheets, ignoring the base and adblocking sheets */
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++) {
struct content *css = c->data.html.stylesheets[i].c;
@ -128,44 +134,39 @@ bool save_complete_html(struct content *c, const char *path, bool index)
if (!css)
continue;
if (save_complete_list_check(css))
if (save_complete_list_check(css, *list))
continue;
is_style = (strcmp(css->url, c->data.html.base_url) == 0);
if (is_style == false) {
if (!save_complete_list_add(css)) {
if (!save_complete_list_add(css, list)) {
warn_user("NoMemory", 0);
return false;
}
}
if (!save_imported_sheets(css, path))
if (!save_imported_sheets(css, path, list))
return false;
if (is_style)
continue; /* don't save <style> elements */
snprintf(spath, sizeof spath, "%s.%x", path,
(unsigned int) css);
snprintf(filename, sizeof filename, "%p", css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url);
css->source_size, &source_len, css->url,
*list);
if (!source) {
warn_user("NoMemory", 0);
return false;
}
error = xosfile_save_stamped(spath, 0xf79,
(byte *) source, (byte *) source + source_len);
res = save_complete_gui_save(path, filename, source_len,
source, CONTENT_CSS);
free(source);
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
if (res == false)
return false;
}
}
/* save objects */
for (i = 0; i != c->data.html.object_count; i++) {
struct content *obj = c->data.html.object[i].content;
@ -173,32 +174,25 @@ bool save_complete_html(struct content *c, const char *path, bool index)
/* skip difficult content types */
if (!obj || obj->type >= CONTENT_OTHER || !obj->source_data)
continue;
if (save_complete_list_check(obj))
if (save_complete_list_check(obj, *list))
continue;
if (!save_complete_list_add(obj)) {
if (!save_complete_list_add(obj, list)) {
warn_user("NoMemory", 0);
return false;
}
if (obj->type == CONTENT_HTML) {
if (!save_complete_html(obj, path, false))
if (!save_complete_html(obj, path, false, list))
return false;
continue;
}
snprintf(spath, sizeof spath, "%s.%x", path,
(unsigned int) obj);
error = xosfile_save_stamped(spath,
ro_content_filetype(obj),
(byte *) obj->source_data,
(byte *) obj->source_data + obj->source_size);
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
snprintf(filename, sizeof filename, "%p", obj);
res = save_complete_gui_save(path, filename,
obj->source_size, obj->source_data, obj->type);
if(res == false)
return false;
}
}
/*save_complete_list_dump();*/
@ -211,7 +205,7 @@ bool save_complete_html(struct content *c, const char *path, bool index)
}
/* rewrite all urls we know about */
if (!rewrite_document_urls(doc, c->data.html.base_url)) {
if (!rewrite_document_urls(doc, c->data.html.base_url, *list)) {
xmlFreeDoc(doc);
warn_user("NoMemory", 0);
return false;
@ -219,12 +213,12 @@ bool save_complete_html(struct content *c, const char *path, bool index)
/* save the html file out last of all */
if (index)
snprintf(spath, sizeof spath, "%s.index", path);
else
snprintf(spath, sizeof spath, "%s.%x", path, (unsigned int)c);
snprintf(filename, sizeof filename, "index");
else
snprintf(filename, sizeof filename, "%p", c);
errno = 0;
if (htmlSaveFileFormat(spath, doc, 0, 0) == -1) {
if (save_complete_htmlSaveFileFormat(path, filename, doc, 0, 0) == -1) {
if (errno)
warn_user("SaveError", strerror(errno));
else
@ -232,18 +226,10 @@ bool save_complete_html(struct content *c, const char *path, bool index)
xmlFreeDoc(doc);
return false;
}
}
xmlFreeDoc(doc);
error = xosfile_set_type(spath, 0xfaf);
if (error) {
LOG(("xosfile_set_type: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
return false;
}
return true;
}
@ -256,48 +242,45 @@ bool save_complete_html(struct content *c, const char *path, bool index)
* \return true on success, false on error and error reported
*/
bool save_imported_sheets(struct content *c, const char *path)
bool save_imported_sheets(struct content *c, const char *path,
struct save_complete_entry **list)
{
char spath[256];
char filename[256];
unsigned int j;
char *source;
int source_len;
os_error *error;
bool res;
for (j = 0; j != c->data.css.import_count; j++) {
struct content *css = c->data.css.imports[j].c;
if (!css)
continue;
if (save_complete_list_check(css))
if (save_complete_list_check(css, *list))
continue;
if (!save_complete_list_add(css)) {
if (!save_complete_list_add(css, list)) {
warn_user("NoMemory", 0);
return false;
}
if (!save_imported_sheets(css, path))
if (!save_imported_sheets(css, path, list))
return false;
snprintf(spath, sizeof spath, "%s.%x", path,
(unsigned int) css);
snprintf(filename, sizeof filename, "%p", css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url);
css->source_size, &source_len, css->url,
*list);
if (!source) {
warn_user("NoMemory", 0);
return false;
}
error = xosfile_save_stamped(spath, 0xf79,
(byte *) source, (byte *) source + source_len);
res = save_complete_gui_save(path, filename, source_len,
source, CONTENT_CSS);
free(source);
if (error) {
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
if (res == false)
return false;
}
}
return true;
@ -352,7 +335,8 @@ void save_complete_init(void)
*/
char * rewrite_stylesheet_urls(const char *source, unsigned int size,
int *osize, const char *base)
int *osize, const char *base,
struct save_complete_entry *list)
{
char *res;
const char *url;
@ -435,11 +419,11 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size,
*osize += match[0].rm_so;
if (result == URL_FUNC_OK) {
content = save_complete_list_find(url);
content = save_complete_list_find(url, list);
if (content) {
/* replace import */
snprintf(buf, sizeof buf, "@import '%x'",
(unsigned int) content);
snprintf(buf, sizeof buf, "@import '%p'",
content);
memcpy(res + *osize, buf, strlen(buf));
*osize += strlen(buf);
} else {
@ -478,13 +462,14 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size,
* \return true on success, false on out of memory
*/
bool rewrite_document_urls(xmlDoc *doc, const char *base)
bool rewrite_document_urls(xmlDoc *doc, const char *base,
struct save_complete_entry *list)
{
xmlNode *node;
for (node = doc->children; node; node = node->next)
if (node->type == XML_ELEMENT_NODE)
if (!rewrite_urls(node, base))
if (!rewrite_urls(node, base, list))
return false;
return true;
@ -501,7 +486,8 @@ bool rewrite_document_urls(xmlDoc *doc, const char *base)
* URLs in the tree rooted at element n are rewritten.
*/
bool rewrite_urls(xmlNode *n, const char *base)
bool rewrite_urls(xmlNode *n, const char *base,
struct save_complete_entry *list)
{
xmlNode *child;
@ -524,14 +510,14 @@ bool rewrite_urls(xmlNode *n, const char *base)
}
/* 1 */
else if (strcmp((const char *) n->name, "object") == 0) {
if (!rewrite_url(n, "data", base))
if (!rewrite_url(n, "data", base, list))
return false;
}
/* 2 */
else if (strcmp((const char *) n->name, "a") == 0 ||
strcmp((const char *) n->name, "area") == 0 ||
strcmp((const char *) n->name, "link") == 0) {
if (!rewrite_url(n, "href", base))
if (!rewrite_url(n, "href", base, list))
return false;
}
/* 3 */
@ -540,7 +526,7 @@ bool rewrite_urls(xmlNode *n, const char *base)
strcmp((const char *) n->name, "input") == 0 ||
strcmp((const char *) n->name, "img") == 0 ||
strcmp((const char *) n->name, "script") == 0) {
if (!rewrite_url(n, "src", base))
if (!rewrite_url(n, "src", base, list))
return false;
}
/* 4 */
@ -561,7 +547,7 @@ bool rewrite_urls(xmlNode *n, const char *base)
char *rewritten = rewrite_stylesheet_urls(
(const char *) content,
strlen((const char *) content),
(int *) &len, base);
(int *) &len, base, list);
xmlFree(content);
if (!rewritten)
return false;
@ -586,7 +572,7 @@ bool rewrite_urls(xmlNode *n, const char *base)
}
/* 6 */
else {
if (!rewrite_url(n, "background", base))
if (!rewrite_url(n, "background", base, list))
return false;
}
@ -598,7 +584,7 @@ bool rewrite_urls(xmlNode *n, const char *base)
* next child */
xmlNode *next = child->next;
if (child->type == XML_ELEMENT_NODE) {
if (!rewrite_urls(child, base))
if (!rewrite_urls(child, base, list))
return false;
}
child = next;
@ -617,7 +603,8 @@ bool rewrite_urls(xmlNode *n, const char *base)
* \return true on success, false on out of memory
*/
bool rewrite_url(xmlNode *n, const char *attr, const char *base)
bool rewrite_url(xmlNode *n, const char *attr, const char *base,
struct save_complete_entry *list)
{
char *url, *data;
char rel[20];
@ -636,12 +623,11 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base)
if (res == URL_FUNC_NOMEM)
return false;
else if (res == URL_FUNC_OK) {
content = save_complete_list_find(url);
content = save_complete_list_find(url, list);
if (content) {
/* found a match */
free(url);
snprintf(rel, sizeof rel, "%x",
(unsigned int) content);
snprintf(rel, sizeof rel, "%p", content);
if (!xmlSetProp(n, (const xmlChar *) attr,
(xmlChar *) rel))
return false;
@ -667,15 +653,16 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base)
* \return true on success, false on out of memory
*/
bool save_complete_list_add(struct content *content)
bool save_complete_list_add(struct content *content,
struct save_complete_entry **list)
{
struct save_complete_entry *entry;
entry = malloc(sizeof (*entry));
if (!entry)
return false;
entry->content = content;
entry->next = save_complete_list;
save_complete_list = entry;
entry->next = *list;
*list = entry;
return true;
}
@ -687,10 +674,11 @@ bool save_complete_list_add(struct content *content)
* \return content if found, 0 otherwise
*/
struct content * save_complete_list_find(const char *url)
struct content * save_complete_list_find(const char *url,
struct save_complete_entry *list)
{
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
for (entry = list; entry; entry = entry->next)
if (strcmp(url, entry->content->url) == 0)
return entry->content;
return 0;
@ -704,10 +692,11 @@ struct content * save_complete_list_find(const char *url)
* \return true if the content is in the save_complete_list
*/
bool save_complete_list_check(struct content *content)
bool save_complete_list_check(struct content *content,
struct save_complete_entry *list)
{
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
for (entry = list; entry; entry = entry->next)
if (entry->content == content)
return true;
return false;
@ -732,14 +721,23 @@ void save_complete_list_dump(void)
* Create the inventory file listing original URLs.
*/
bool save_complete_inventory(const char *path)
bool save_complete_inventory(const char *path,
struct save_complete_entry *list)
{
char spath[256];
char urlpath[256];
FILE *fp;
char *pathstring, *standardpath = (path[0] == '/') ?
(char *)(path + 1) : (char *)path;
snprintf(spath, sizeof spath, "%s.Inventory", path);
fp = fopen(spath, "w");
snprintf(urlpath, sizeof urlpath, "file:///%s/Inventory",
standardpath);
pathstring = url_to_path(urlpath);
if (pathstring == NULL) {
warn_user("NoMemory", 0);
return false;
}
fp = fopen(pathstring, "w");
free(pathstring);
if (!fp) {
LOG(("fopen(): errno = %i", errno));
warn_user("SaveError", strerror(errno));
@ -747,10 +745,8 @@ bool save_complete_inventory(const char *path)
}
struct save_complete_entry *entry;
for (entry = save_complete_list; entry; entry = entry->next)
fprintf(fp, "%x %s\n",
(unsigned int) entry->content,
entry->content->url);
for (entry = list; entry; entry = entry->next)
fprintf(fp, "%p %s\n", entry->content, entry->content->url);
fclose(fp);

42
desktop/save_complete.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Save HTML document with dependencies (interface).
*/
#ifndef _NETSURF_DESKTOP_SAVE_COMPLETE_H_
#define _NETSURF_DESKTOP_SAVE_COMPLETE_H_
#include <stdbool.h>
#include <libxml/HTMLtree.h>
#include "content/content.h"
struct content;
void save_complete_init(void);
bool save_complete(struct content *c, const char *path);
bool save_complete_gui_save(const char *path, const char *filename,
size_t len, const char *sourcedata, content_type type);
int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
xmlDocPtr cur, const char *encoding, int format);
#endif

705
desktop/search.c Normal file
View File

@ -0,0 +1,705 @@
/*
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Free text search (core)
*/
#include "utils/config.h"
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/search.h"
#include "desktop/selection.h"
#include "render/box.h"
#include "render/html.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
#ifndef NOF_ELEMENTS
#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
#endif
struct list_entry {
unsigned start_idx; /* start position of match */
unsigned end_idx; /* end of match */
struct box *start_box; /* used only for html contents */
struct box *end_box;
struct selection *sel;
struct list_entry *prev;
struct list_entry *next;
};
struct search_context {
struct browser_window *bw;
struct content *content;
char *string;
bool prev_case_sens;
bool newsearch;
bool insert;
void *p; /* front-specific data */
struct search_callbacks *callbacks;
struct list_entry *found;
struct list_entry *current; /* first for select all */
};
static void search_text(const char *string, int string_len,
struct search_context *context, search_flags_t flags);
static const char *find_pattern(const char *string, int s_len,
const char *pattern, int p_len, bool case_sens,
unsigned int *m_len);
static bool find_occurrences_html(const char *pattern, int p_len,
struct box *cur, bool case_sens,
struct search_context *context);
static bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens,
struct search_context *context);
static struct list_entry *add_entry(unsigned start_idx, unsigned end_idx,
struct search_context *context);
static void free_matches(struct search_context *context);
/**
* create a search_context
* \param bw the browser_window the search_context is connected to
* \param callbacks the callbacks to modify appearance according to results
* \param p the pointer to send to the callbacks
* \return true for success
*/
bool search_create_context(struct browser_window *bw,
struct search_callbacks *callbacks, void *p)
{
struct search_context *context = malloc(sizeof(struct search_context));
struct list_entry *search_head = malloc(sizeof(struct list_entry));
if ((context == NULL) || (search_head == NULL)) {
warn_user("NoMemory", 0);
return false;
}
if (bw->search_context != NULL)
search_destroy_context(bw->search_context);
search_head->start_idx = 0;
search_head->end_idx = 0;
search_head->start_box = NULL;
search_head->end_box = NULL;
search_head->sel = NULL;
search_head->prev = NULL;
search_head->next = NULL;
context->found = search_head;
context->current = NULL;
context->content = NULL;
context->string = NULL;
context->prev_case_sens = false;
context->newsearch = true;
context->insert = true;
context->bw = bw;
context->callbacks = callbacks;
context->p = p;
bw->search_context = context;
return true;
}
/**
* to simplify calls to search_step(); checks that the browser_window is
* non-NULL, creates a new search_context in case of a new search
* \param bw the browser_window the search refers to
* \param callbacks the callbacks to modify appearance according to results
* \param p a pointer returned to the callbacks
* \return true for success
*/
bool search_verify_new(struct browser_window *bw,
struct search_callbacks *callbacks, void *p)
{
if (bw == NULL)
return false;
if (bw->search_context == NULL)
return search_create_context(bw, callbacks, p);
return true;
}
/**
* Begins/continues the search process
* Note that this may be called many times for a single search.
*
* \param bw the browser_window to search in
* \param flags the flags forward/back etc
* \param string the string to match
*/
void search_step(struct search_context *context, search_flags_t flags,
const char *string)
{
int string_len;
int i = 0;
if ((context == NULL) || (context->callbacks == NULL)) {
warn_user("SearchError", 0);
return;
}
if (context->callbacks->add_recent != NULL)
context->callbacks->add_recent(string, context->p);
string_len = strlen(string);
for(i = 0; i < string_len; i++)
if (string[i] != '#' && string[i] != '*') break;
if (i >= string_len) {
free_matches(context);
if (context->callbacks->status != NULL)
context->callbacks->status(true, context->p);
if (context->callbacks->back_state != NULL)
context->callbacks->back_state(false, context->p);
if (context->callbacks->forward_state != NULL)
context->callbacks->forward_state(false, context->p);
gui_window_set_scroll(context->bw->window, 0, 0);
return;
}
search_text(string, string_len, context, flags);
}
/**
* Release the memory used by the list of matches,
* deleting selection objects too
*/
void free_matches(struct search_context *context)
{
struct list_entry *a = context->found->next;
struct list_entry *b;
/* empty the list before clearing and deleting the
selections because the the clearing updates the
screen immediately, causing nested accesses to the list */
context->found->prev = NULL;
context->found->next = NULL;
for (; a; a = b) {
b = a->next;
if (a->sel) {
selection_clear(a->sel, true);
selection_destroy(a->sel);
}
free(a);
}
}
/**
* Search for a string in the box tree
*
* \param string the string to search for
* \param string_len length of search string
*/
void search_text(const char *string, int string_len,
struct search_context *context, search_flags_t flags)
{
struct rect bounds;
struct content *c;
struct box *box;
bool case_sensitive, forwards, showall;
case_sensitive = ((flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) ?
true : false;
forwards = ((flags & SEARCH_FLAG_FORWARDS) != 0) ? true : false;
showall = ((flags & SEARCH_FLAG_SHOWALL) != 0) ? true : false;
if (context->bw == NULL)
return;
c = context->bw->current_content;
/* only handle html contents */
if ((!c) || (c->type != CONTENT_HTML &&
c->type != CONTENT_TEXTPLAIN))
return;
box = c->data.html.layout;
if (!box)
return;
/* LOG(("do_search '%s' - '%s' (%p, %p) %p (%d, %d) %d",
search_data.string, string, search_data.content, c, search_data.found->next,
search_data.prev_case_sens, case_sens, forwards)); */
/* check if we need to start a new search or continue an old one */
if (context->newsearch) {
bool res;
if (context->string != NULL)
free(context->string);
context->current = NULL;
free_matches(context);
context->string = malloc(string_len + 1);
if (context->string != NULL) {
memcpy(context->string, string, string_len);
context->string[string_len] = '\0';
}
if ((context->callbacks != NULL) &&
(context->callbacks->hourglass != NULL))
context->callbacks->hourglass(true, context->p);
if (c->type == CONTENT_HTML)
res = find_occurrences_html(string, string_len,
box, case_sensitive, context);
else {
assert(c->type == CONTENT_TEXTPLAIN);
res = find_occurrences_text(string, string_len,
c, case_sensitive, context);
}
if (!res) {
free_matches(context);
if ((context->callbacks != NULL) &&
(context->callbacks->hourglass !=
NULL))
context->callbacks->hourglass(false,
context->p);
return;
}
if ((context->callbacks != NULL) &&
(context->callbacks->hourglass != NULL))
context->callbacks->hourglass(false, context->p);
context->content = c;
context->prev_case_sens = case_sensitive;
/* LOG(("%d %p %p (%p, %p)", new, search_data.found->next, search_data.current,
search_data.current->prev, search_data.current->next)); */
/* new search, beginning at the top of the page */
context->current = context->found->next;
context->newsearch = false;
}
else if (context->current != NULL) {
/* continued search in the direction specified */
if (forwards) {
if (context->current->next)
context->current = context->current->next;
}
else {
if (context->current->prev)
context->current = context->current->prev;
}
}
if (context->callbacks == NULL)
return;
if (context->callbacks->status != NULL)
context->callbacks->status((context->current != NULL),
context->p);
search_show_all(showall, context);
if (context->callbacks->back_state != NULL)
context->callbacks->back_state((context->current != NULL) &&
(context->current->prev != NULL),
context->p);
if (context->callbacks->forward_state != NULL)
context->callbacks->forward_state((context->current != NULL) &&
(context->current->next != NULL), context->p);
if (context->current == NULL)
return;
switch (c->type) {
case CONTENT_HTML:
/* get box position and jump to it */
box_coords(context->current->start_box,
&bounds.x0, &bounds.y0);
/* \todo: move x0 in by correct idx */
box_coords(context->current->end_box,
&bounds.x1, &bounds.y1);
/* \todo: move x1 in by correct idx */
bounds.x1 += context->current->end_box->width;
bounds.y1 += context->current->end_box->height;
break;
default:
assert(c->type == CONTENT_TEXTPLAIN);
textplain_coords_from_range(c,
context->current->start_idx,
context->current->end_idx, &bounds);
break;
}
gui_window_scroll_visible(context->bw->window,
bounds.x0, bounds.y0, bounds.x1, bounds.y1);
}
/**
* Find the first occurrence of 'match' in 'string' and return its index
*
* \param string the string to be searched (unterminated)
* \param s_len length of the string to be searched
* \param pattern the pattern for which we are searching (unterminated)
* \param p_len length of pattern
* \param case_sens true iff case sensitive match required
* \param m_len accepts length of match in bytes
* \return pointer to first match, NULL if none
*/
const char *find_pattern(const char *string, int s_len, const char *pattern,
int p_len, bool case_sens, unsigned int *m_len)
{
struct { const char *ss, *s, *p; bool first; } context[16];
const char *ep = pattern + p_len;
const char *es = string + s_len;
const char *p = pattern - 1; /* a virtual '*' before the pattern */
const char *ss = string;
const char *s = string;
bool first = true;
int top = 0;
while (p < ep) {
bool matches;
if (p < pattern || *p == '*') {
char ch;
/* skip any further asterisks; one is the same as many
*/
do p++; while (p < ep && *p == '*');
/* if we're at the end of the pattern, yes, it matches
*/
if (p >= ep) break;
/* anything matches a # so continue matching from
here, and stack a context that will try to match
the wildcard against the next character */
ch = *p;
if (ch != '#') {
/* scan forwards until we find a match for
this char */
if (!case_sens) ch = toupper(ch);
while (s < es) {
if (case_sens) {
if (*s == ch) break;
} else if (toupper(*s) == ch)
break;
s++;
}
}
if (s < es) {
/* remember where we are in case the match
fails; we may then resume */
if (top < (int)NOF_ELEMENTS(context)) {
context[top].ss = ss;
context[top].s = s + 1;
context[top].p = p - 1;
/* ptr to last asterisk */
context[top].first = first;
top++;
}
if (first) {
ss = s;
/* remember first non-'*' char */
first = false;
}
matches = true;
}
else
matches = false;
}
else if (s < es) {
char ch = *p;
if (ch == '#')
matches = true;
else {
if (case_sens)
matches = (*s == ch);
else
matches = (toupper(*s) == toupper(ch));
}
if (matches && first) {
ss = s; /* remember first non-'*' char */
first = false;
}
}
else
matches = false;
if (matches) {
p++; s++;
}
else {
/* doesn't match, resume with stacked context if we have one */
if (--top < 0) return NULL; /* no match, give up */
ss = context[top].ss;
s = context[top].s;
p = context[top].p;
first = context[top].first;
}
}
/* end of pattern reached */
*m_len = max(s - ss, 1);
return ss;
}
/**
* Finds all occurrences of a given string in the html box tree
*
* \param pattern the string pattern to search for
* \param p_len pattern length
* \param cur pointer to the current box
* \param case_sens whether to perform a case sensitive search
* \return true on success, false on memory allocation failure
*/
bool find_occurrences_html(const char *pattern, int p_len, struct box *cur,
bool case_sens, struct search_context *context)
{
struct box *a;
/* ignore this box, if there's no visible text */
if (!cur->object && cur->text) {
const char *text = cur->text;
unsigned length = cur->length;
while (length > 0) {
struct list_entry *entry;
unsigned match_length;
unsigned match_offset;
const char *new_text;
const char *pos = find_pattern(text, length,
pattern, p_len, case_sens,
&match_length);
if (!pos) break;
/* found string in box => add to list */
match_offset = pos - cur->text;
entry = add_entry(cur->byte_offset + match_offset,
cur->byte_offset +
match_offset +
match_length, context);
if (!entry)
return false;
entry->start_box = cur;
entry->end_box = cur;
new_text = pos + match_length;
length -= (new_text - text);
text = new_text;
}
}
/* and recurse */
for (a = cur->children; a; a = a->next) {
if (!find_occurrences_html(pattern, p_len, a, case_sens,
context))
return false;
}
return true;
}
/**
* Finds all occurrences of a given string in a textplain content
*
* \param pattern the string pattern to search for
* \param p_len pattern length
* \param c the content to be searched
* \param case_sens wheteher to perform a case sensitive search
* \return true on success, false on memory allocation failure
*/
bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens,
struct search_context *context)
{
int nlines = textplain_line_count(c);
int line;
for(line = 0; line < nlines; line++) {
size_t offset, length;
const char *text = textplain_get_line(c, line,
&offset, &length);
if (text) {
while (length > 0) {
struct list_entry *entry;
unsigned match_length;
size_t start_idx;
const char *new_text;
const char *pos = find_pattern(text, length,
pattern, p_len, case_sens,
&match_length);
if (!pos) break;
/* found string in line => add to list */
start_idx = offset + (pos - text);
entry = add_entry(start_idx, start_idx +
match_length, context);
if (!entry)
return false;
new_text = pos + match_length;
offset += (new_text - text);
length -= (new_text - text);
text = new_text;
}
}
}
return true;
}
/**
* Determines whether any portion of the given text box should be
* selected because it matches the current search string.
*
* \param g gui window
* \param start_offset byte offset within text of string to be checked
* \param end_offset byte offset within text
* \param start_idx byte offset within string of highlight start
* \param end_idx byte offset of highlight end
* \return true iff part of the box should be highlighted
*/
bool gui_search_term_highlighted(struct gui_window *g,
unsigned start_offset, unsigned end_offset,
unsigned *start_idx, unsigned *end_idx,
struct search_context *context)
{
if (g == context->bw->window) {
struct list_entry *a;
for(a = context->found->next; a; a = a->next)
if (a->sel && selection_defined(a->sel) &&
selection_highlighted(a->sel,
start_offset, end_offset,
start_idx, end_idx))
return true;
}
return false;
}
/**
* Specifies whether all matches or just the current match should
* be highlighted in the search text.
*/
void search_show_all(bool all, struct search_context *context)
{
struct list_entry *a;
for (a = context->found->next; a; a = a->next) {
bool add = true;
if (!all && a != context->current) {
add = false;
if (a->sel) {
selection_clear(a->sel, true);
selection_destroy(a->sel);
a->sel = NULL;
}
}
if (add && !a->sel) {
a->sel = selection_create(context->bw);
if (a->sel) {
struct content *c = context->bw->
current_content;
switch (c->type) {
case CONTENT_HTML:
selection_init(a->sel,
c->data.html.layout);
break;
default:
assert(c->type ==
CONTENT_TEXTPLAIN);
selection_init(a->sel, NULL);
break;
}
selection_set_start(a->sel, a->start_idx);
selection_set_end(a->sel, a->end_idx);
}
}
}
}
/**
* Add a new entry to the list of matches
*
* \param start_idx offset of match start within textual representation
* \param end_idx offset of match end
* \return pointer to added entry, NULL iff failed
*/
struct list_entry *add_entry(unsigned start_idx, unsigned end_idx,
struct search_context *context)
{
struct list_entry *entry;
/* found string in box => add to list */
entry = calloc(1, sizeof(*entry));
if (!entry) {
warn_user("NoMemory", 0);
return NULL;
}
entry->start_idx = start_idx;
entry->end_idx = end_idx;
entry->sel = NULL;
entry->next = 0;
entry->prev = context->found->prev;
if (context->found->prev == NULL)
context->found->next = entry;
else
context->found->prev->next = entry;
context->found->prev = entry;
return entry;
}
/**
* Ends the search process, invalidating all state
* freeing the list of found boxes
*/
void search_destroy_context(struct search_context *context)
{
if (context->bw != NULL)
context->bw->search_context = NULL;
if ((context->string != NULL) && (context->callbacks != NULL) &&
(context->callbacks->add_recent != NULL)) {
context->callbacks->add_recent(context->string, context->p);
free(context->string);
}
free_matches(context);
free(context);
}

91
desktop/search.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_DESKTOP_SEARCH_H_
#define _NETSURF_DESKTOP_SEARCH_H_
#include <ctype.h>
#include <string.h>
struct search_context;
typedef enum {
SEARCH_FLAG_CASE_SENSITIVE = (1 << 0),
SEARCH_FLAG_FORWARDS = (1 << 1),
SEARCH_FLAG_SHOWALL = (1 << 2)
} search_flags_t;
/**
* called to clear the context; 'renews' the search too
*/
void search_destroy_context(struct search_context *context);
/**
* Change the displayed search status.
* \param found search pattern matched in text
* \param p the pointer sent to search_step() / search_create_context()
*/
typedef void (*search_status_callback)(bool found, void *p);
/**
* display hourglass while searching
* \param active start/stop indicator
* \param p the pointer sent to search_step() / search_create_context()
*/
typedef void (*search_hourglass_callback)(bool active, void *p);
/**
* add search string to recent searches list
* front has full liberty how to implement the bare notification;
* core gives no guarantee of the integrity of the const char *
* \param string search pattern
* \param p the pointer sent to search_step() / search_create_context()
*/
typedef void (*search_add_recent_callback)(const char *string, void *p);
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_step() / search_create_context()
*/
typedef void (*search_forward_state_callback)(bool active, void *p);
/**
* activate search back button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_step() / search_create_context()
*/
typedef void (*search_back_state_callback)(bool active, void *p);
struct search_callbacks {
search_forward_state_callback forward_state;
search_back_state_callback back_state;
search_status_callback status;
search_hourglass_callback hourglass;
search_add_recent_callback add_recent;
};
bool search_verify_new(struct browser_window *bw,
struct search_callbacks *callbacks, void *p);
void search_step(struct search_context *context, search_flags_t flags,
const char * string);
bool search_create_context(struct browser_window *bw,
struct search_callbacks *callbacks, void *p);
void search_show_all(bool all, struct search_context *context);
#endif

292
desktop/searchweb.c Normal file
View File

@ -0,0 +1,292 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* web search (core)
*/
#include "utils/config.h"
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "content/fetchcache.h"
#include "content/fetch.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
static struct search_provider {
char *name; /**< readable name such as 'google', 'yahoo', etc */
char *hostname; /**< host address such as www.google.com */
char *searchstring; /** < such as "www.google.com?search=%s" */
char *ico; /** < location of domain's favicon */
} current_search_provider;
static struct content *search_ico = NULL;
char *search_engines_file_location;
char *search_default_ico_location;
/**
* creates a new browser window according to the search term
* \param searchterm such as "my search term"
*/
bool search_web_new_window(struct browser_window *bw, const char *searchterm)
{
char *encsearchterm;
char *url;
if (url_escape(searchterm,0, true, NULL, &encsearchterm) !=
URL_FUNC_OK)
return false;
url = search_web_get_url(encsearchterm);
free(encsearchterm);
browser_window_create(url, bw, NULL, false, true);
free(url);
return true;
}
/** simplistic way of checking whether an entry from the url bar is an
* url / a search; could be improved to properly test terms
*/
bool search_is_url(const char *url)
{
char *url2, *host;
if (url_normalize(url, &url2) != URL_FUNC_OK)
return false;
if (url_host(url2, &host) != URL_FUNC_OK)
return false;
return true;
}
/**
* caches the details of the current web search provider
* \param reference the enum value of the provider
* browser init code [as well as changing preferences code] should call
* search_web_provider_details(option_search_provider)
*/
void search_web_provider_details(int reference)
{
char buf[300];
int ref = 0;
if (search_engines_file_location == NULL)
return;
FILE *f = fopen(search_engines_file_location, "r");
if (f == NULL)
return;
while (fgets(buf, sizeof(buf), f) != NULL) {
if (buf[0] == '\0')
continue;
buf[strlen(buf)-1] = '\0';
if (ref++ == (int)reference)
break;
}
if (current_search_provider.name != NULL)
free(current_search_provider.name);
current_search_provider.name = strdup(strtok(buf, "|"));
if (current_search_provider.hostname != NULL)
free(current_search_provider.hostname);
current_search_provider.hostname = strdup(strtok(NULL, "|"));
if (current_search_provider.searchstring != NULL)
free(current_search_provider.searchstring);
current_search_provider.searchstring = strdup(strtok(NULL, "|"));
if (current_search_provider.ico != NULL)
free(current_search_provider.ico);
current_search_provider.ico = strdup(strtok(NULL, "|"));
return;
}
/**
* escapes a search term then creates the appropriate url from it
*/
char *search_web_from_term(const char *searchterm)
{
char *encsearchterm, *url;
if (url_escape(searchterm, 0, true, NULL, &encsearchterm)
!= URL_FUNC_OK)
return strdup(searchterm);
url = search_web_get_url(encsearchterm);
free(encsearchterm);
return url;
}
/** accessor for global search provider name */
char *search_web_provider_name(void)
{
if (current_search_provider.name)
return strdup(current_search_provider.name);
return strdup("google");
}
/** accessor for global search provider hostname */
char *search_web_provider_host(void)
{
if (current_search_provider.hostname)
return strdup(current_search_provider.hostname);
return strdup("www.google.com");
}
/** accessor for global search provider ico name */
char *search_web_ico_name(void)
{
if (current_search_provider.ico)
return strdup(current_search_provider.ico);
return strdup("http://www.google.com/favicon.ico");
}
/**
* creates a full url from an encoded search term
*/
char *search_web_get_url(const char *encsearchterm)
{
char *pref, *ret;
int len;
if (current_search_provider.searchstring)
pref = strdup(current_search_provider.searchstring);
else
pref = strdup("http://www.google.com/search?q=%s");
if (pref == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
len = strlen(encsearchterm) + strlen(pref);
ret = malloc(len -1); /* + '\0' - "%s" */
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(pref);
return NULL;
}
snprintf(ret, len-1, pref, encsearchterm);
free(pref);
return ret;
}
/**
* function to retrieve the search web ico, from cache / from local
* filesystem / from the web
* \param localdefault true when there is no appropriate favicon
* update the search_ico cache else delay until fetcher callback
*/
void search_web_retrieve_ico(bool localdefault)
{
char *url;
if (localdefault) {
if (search_default_ico_location == NULL)
return;
url = malloc(SLEN("file://") + strlen(
search_default_ico_location) + 1);
if (url == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
strcpy(url, "file://");
strcat(url, search_default_ico_location);
} else {
url = search_web_ico_name();
}
struct content *icocontent = NULL;
if (url == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
icocontent = fetchcache(url, search_web_ico_callback,
0, 0, 20, 20, true, 0,
0, false, false);
free(url);
if (icocontent == NULL)
return;
fetchcache_go(icocontent, 0, search_web_ico_callback,
0, 0, 20, 20,
0, 0, false, 0);
if (icocontent == NULL)
LOG(("web search ico loading delayed"));
else
search_ico = icocontent;
}
/**
* returns a reference to the static global search_ico [ / NULL]
* caller may adjust ico's settings; clearing / free()ing is the core's
* responsibility
*/
struct content *search_web_ico(void)
{
return search_ico;
}
/**
* callback function to cache ico then notify front when successful
* else retry default from local file system
*/
void search_web_ico_callback(content_msg msg, struct content *ico,
intptr_t p1, intptr_t p2, union content_msg_data data)
{
switch (msg) {
case CONTENT_MSG_LOADING:
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got favicon '%s'", ico->url));
if (ico->type == CONTENT_ICO) {
search_ico = ico; /* cache */
gui_window_set_search_ico(search_ico);
} else {
search_web_retrieve_ico(true);
}
break;
case CONTENT_MSG_LAUNCH:
case CONTENT_MSG_ERROR:
LOG(("favicon %s error: %s", ico->url, data.error));
ico = 0;
search_web_retrieve_ico(true);
break;
case CONTENT_MSG_STATUS:
case CONTENT_MSG_NEWPTR:
case CONTENT_MSG_AUTH:
case CONTENT_MSG_SSL:
break;
default:
assert(0);
}
}

79
desktop/searchweb.h Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_DESKTOP_SEARCH_WEB_H_
#define _NETSURF_DESKTOP_SEARCH_WEB_H_
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "desktop/browser.h"
extern char *search_engines_file_location;
extern char *search_default_ico_location;
/**
* open new tab/window for web search term
*/
bool search_web_new_window(struct browser_window *bw, const char *searchterm);
/**
* retrieve full search url from unencoded search term
*/
char *search_web_from_term(const char *searchterm);
/**
* retrieve full search url from encoded web search term
*/
char *search_web_get_url(const char *encsearchterm);
/**
* cache details of web search provider from file
*/
void search_web_provider_details(int reference);
/**
* retrieve name of web search provider
*/
char *search_web_provider_name(void);
/**
* retrieve hostname of web search provider
*/
char *search_web_provider_host(void);
/**
* retrieve name of .ico for search bar
*/
char *search_web_ico_name(void);
/**
* check whether an URL is in fact a search term
* \param url the url being checked
* \return true for url, false for search
*/
bool search_is_url(const char *url);
void search_web_retrieve_ico(bool localdefault);
struct content *search_web_ico(void);
void search_web_ico_callback(content_msg msg, struct content *ico,
intptr_t p1, intptr_t p2, union content_msg_data data);
#endif

74
framebuffer/fb_search.c Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <string.h>
#include "utils/log.h"
/* callback functions for search implementation */
static void gui_search_set_status(bool found, void *p);
static void gui_search_set_hourglass(bool active, void *p);
static void gui_search_add_recent(const char *string, void *p);
static void gui_search_set_forward_state(bool active, void *p);
static void gui_search_set_back_state(bool active, void *p);
/**
* Change the displayed search status.
* \param found search pattern matched in text
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_status(bool found, void *p)
{
}
/**
* display hourglass while searching
* \param active start/stop indicator
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_hourglass(bool active, void *p)
{
}
/**
* add search string to recent searches list
* \param string search pattern
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_add_recent(const char *string, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_forward_state(bool active, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void gui_search_set_back_state(bool active, void *p)
{
}

View File

@ -30,8 +30,9 @@ static const gchar *authors[] = {
"Matthew Hambley", "Rob Jackson", "Jeffrey Lee", "Phil Mellor",
"Philip Pemberton", "Darren Salt", "Andrew Timmins",
"John Tytgat", "Chris Williams",
"\nGoogle Summer of Code Contributors:", "Adam Blokus",
"Sean Fox", "Michael Lester", "Andrew Sidwell", NULL
"\nGoogle Summer of Code Contributors:", "Mark Benjamin",
"Adam Blokus", "Paul Blokus", "Sean Fox",
"Michael Lester", "Andrew Sidwell", "Bo Yang", NULL
};
static const gchar *translators = "Sebastian Barthel\nBruno D'Arcangeli\n"

View File

@ -2,6 +2,7 @@
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
* Copyright 2008 Mike Lester <element3260@gmail.com>
* Copyright 2009 Daniel Silverstone <dsilvers@netsurf-browser.org>
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -27,17 +28,20 @@
#include <glade/glade.h>
#include "desktop/options.h"
#include "desktop/print.h"
#include "desktop/searchweb.h"
#include "gtk/options.h"
#include "gtk/gtk_gui.h"
#include "gtk/gtk_scaffolding.h"
#include "gtk/gtk_theme.h"
#include "gtk/dialogs/gtk_options.h"
#include "gtk/gtk_window.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "utils/messages.h"
GtkDialog *wndPreferences;
GtkDialog *wndPreferences = NULL;
static GladeXML *gladeFile;
static gchar *glade_location;
static struct browser_window *current_browser;
static int proxy_type;
@ -45,6 +49,7 @@ static float animation_delay;
static void dialog_response_handler (GtkDialog *dlg, gint res_id);
static gboolean on_dialog_close (GtkDialog *dlg, gboolean stay_alive);
static void nsgtk_options_theme_combo(void);
/* Declares both widget and callback */
#define DECLARE(x) \
@ -97,6 +102,12 @@ DECLARE(checkRequestOverwrite);
DECLARE(fileChooserDownloads);
DECLARE(checkFocusNew);
DECLARE(checkNewBlank);
DECLARE(checkUrlSearch);
DECLARE(comboSearch);
DECLARE(combotheme);
DECLARE(buttonaddtheme);
DECLARE(sourceButtonTab);
static GtkWidget *sourceButtonWindow;
DECLARE(spinMarginTop);
DECLARE(spinMarginBottom);
@ -125,7 +136,9 @@ DECLARE(setDefaultExportOptions);
GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent)
{
glade_location = g_strconcat(res_dir_location, "options.glade", NULL);
char glade_location[strlen(res_dir_location) + SLEN("options.glade")
+ 1];
sprintf(glade_location, "%soptions.glade", res_dir_location);
LOG(("Using '%s' as Glade template file", glade_location));
gladeFile = glade_xml_new(glade_location, NULL, NULL);
@ -133,7 +146,13 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent)
wndPreferences = GTK_DIALOG(glade_xml_get_widget(gladeFile,
"dlgPreferences"));
gtk_window_set_transient_for (GTK_WINDOW(wndPreferences), parent);
FIND_WIDGET(sourceButtonTab);
FIND_WIDGET(sourceButtonWindow);
GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(
sourceButtonWindow));
gtk_radio_button_set_group(GTK_RADIO_BUTTON(sourceButtonTab), group);
/* set the widgets to reflect the current options */
nsgtk_options_load();
@ -188,6 +207,12 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent)
CONNECT(checkFocusNew, "toggled");
CONNECT(checkNewBlank, "toggled");
CONNECT(checkUrlSearch, "toggled");
CONNECT(comboSearch, "changed");
CONNECT(combotheme, "changed");
CONNECT(buttonaddtheme, "clicked");
CONNECT(sourceButtonTab, "toggled");
CONNECT(spinMarginTop, "value-changed");
CONNECT(spinMarginBottom, "value-changed");
@ -247,11 +272,11 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent)
(value)); \
} while (0)
#define SET_FILE_CHOOSER(widgt, value) \
#define SET_FILE_CHOOSER(widget, value) \
do { \
(widgt) = glade_xml_get_widget(gladeFile, #widgt); \
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER((widgt)), \
(value)); \
(widget) = glade_xml_get_widget(gladeFile, #widget); \
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(\
(widget)), (value)); \
} while (0)
#define SET_BUTTON(widget) \
@ -262,22 +287,21 @@ GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent)
void nsgtk_options_load(void)
{
GtkVBox *combolanguagevbox;
gchar *languagefile;
GtkBox *box;
char languagefile[strlen(res_dir_location) + SLEN("languages") + 1];
const char *default_accept_language =
option_accept_language ? option_accept_language : "en";
int combo_row_count = 0;
int active_language = 0;
int proxytype = 0;
FILE *fp;
char buf[20];
char buf[50];
/* Create combobox */
combolanguagevbox =
GTK_VBOX(glade_xml_get_widget(gladeFile, "combolanguagevbox"));
box = GTK_BOX(glade_xml_get_widget(gladeFile, "combolanguagevbox"));
comboLanguage = gtk_combo_box_new_text();
languagefile = g_strconcat(res_dir_location, "languages", NULL);
sprintf(languagefile, "%slanguages", res_dir_location);
/* Populate combobox from languages file */
fp = fopen((const char *) languagefile, "r");
@ -309,10 +333,11 @@ void nsgtk_options_load(void)
/** \todo localisation */
gtk_widget_set_tooltip_text(GTK_WIDGET(comboLanguage),
"set preferred language for web pages");
gtk_box_pack_start(GTK_BOX(combolanguagevbox),
comboLanguage, FALSE, FALSE, 0);
gtk_box_pack_start(box, comboLanguage, FALSE, FALSE, 0);
gtk_widget_show(comboLanguage);
nsgtk_options_theme_combo();
SET_ENTRY(entryHomePageURL,
option_homepage_url ? option_homepage_url : "");
SET_BUTTON(setCurrentPage);
@ -380,7 +405,12 @@ void nsgtk_options_load(void)
SET_CHECK(checkFocusNew, option_focus_new);
SET_CHECK(checkNewBlank, option_new_blank);
SET_CHECK(checkUrlSearch, option_search_url_bar);
SET_COMBO(comboSearch, option_search_provider);
SET_BUTTON(buttonaddtheme);
SET_CHECK(sourceButtonTab, option_source_tab);
SET_SPIN(spinMarginTop, option_margin_top);
SET_SPIN(spinMarginBottom, option_margin_bottom);
SET_SPIN(spinMarginLeft, option_margin_left);
@ -417,6 +447,48 @@ static gboolean on_dialog_close (GtkDialog *dlg, gboolean stay_alive)
}
return stay_alive;
}
static void nsgtk_options_theme_combo(void) {
/* populate theme combo from themelist file */
GtkBox *box = GTK_BOX(glade_xml_get_widget(gladeFile, "themehbox"));
char buf[50];
combotheme = gtk_combo_box_new_text();
size_t len = SLEN("themelist") + strlen(res_dir_location) + 1;
char themefile[len];
if ((combotheme == NULL) || (box == NULL)) {
warn_user(messages_get("NoMemory"), 0);
return;
}
snprintf(themefile, len, "%sthemelist", res_dir_location);
FILE *fp = fopen((const char *)themefile, "r");
if (fp == NULL) {
LOG(("Failed opening themes file"));
warn_user("FileError", (const char *) themefile);
return;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* Ignore blank lines */
if (buf[0] == '\0')
continue;
/* Remove trailing \n */
buf[strlen(buf) - 1] = '\0';
gtk_combo_box_append_text(GTK_COMBO_BOX(combotheme), buf);
}
gtk_combo_box_set_active(GTK_COMBO_BOX(combotheme),
option_current_theme);
gtk_box_pack_start(box, combotheme, FALSE, TRUE, 0);
gtk_widget_show(combotheme);
}
bool nsgtk_options_combo_theme_add(const char *themename)
{
if (wndPreferences == NULL)
return false;
gtk_combo_box_append_text(GTK_COMBO_BOX(combotheme), themename);
return true;
}
/* Defines the callback functions for all widgets and specifies
@ -642,42 +714,44 @@ BUTTON_CLICKED(fontPreview)
END_HANDLER
COMBO_CHANGED(comboButtonType, option_button_type)
struct gui_window *current = window_list;
nsgtk_scaffolding *current = scaf_list;
option_button_type++;
/* value of 0 is reserved for 'unset' */
while (current) {
nsgtk_scaffolding_reset_offset(current);
switch(option_button_type) {
case 0:
gtk_toolbar_set_style(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
case 1:
gtk_toolbar_set_style(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_ICON_SIZE_LARGE_TOOLBAR);
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
case 2:
gtk_toolbar_set_style(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_TOOLBAR_BOTH);
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
case 3:
gtk_toolbar_set_style(
GTK_TOOLBAR(current->scaffold->tool_bar),
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_TOOLBAR_BOTH);
gtk_toolbar_set_icon_size(
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
case 4:
gtk_toolbar_set_style(
GTK_TOOLBAR(nsgtk_scaffolding_toolbar(current)),
GTK_TOOLBAR_TEXT);
default:
break;
}
current = current->next;
current = nsgtk_scaffolding_iterate(current);
}
END_HANDLER
@ -703,6 +777,114 @@ END_HANDLER
CHECK_CHANGED(checkNewBlank, option_new_blank)
END_HANDLER
CHECK_CHANGED(checkUrlSearch, option_search_url_bar)
END_HANDLER
COMBO_CHANGED(comboSearch, option_search_provider)
nsgtk_scaffolding *current = scaf_list;
char *name;
/* refresh web search prefs from file */
search_web_provider_details(option_search_provider);
/* retrieve ico */
search_web_retrieve_ico(false);
/* callback may handle changing gui */
if (search_web_ico() != NULL)
gui_window_set_search_ico(search_web_ico());
/* set entry */
name = search_web_provider_name();
if (name == NULL) {
warn_user(messages_get("NoMemory"), 0);
continue;
}
char content[strlen(name) + SLEN("Search ") + 1];
sprintf(content, "Search %s", name);
free(name);
while (current) {
nsgtk_scaffolding_set_websearch(current, content);
current = nsgtk_scaffolding_iterate(current);
}
END_HANDLER
COMBO_CHANGED(combotheme, option_current_theme)
nsgtk_scaffolding *current = scaf_list;
char *name;
if (option_current_theme != 0) {
if (nsgtk_theme_name() != NULL)
free(nsgtk_theme_name());
name = strdup(gtk_combo_box_get_active_text(
GTK_COMBO_BOX(combotheme)));
if (name == NULL) {
warn_user(messages_get("NoMemory"), 0);
continue;
}
nsgtk_theme_set_name(name);
nsgtk_theme_prepare();
} else if (nsgtk_theme_name() != NULL) {
free(nsgtk_theme_name());
nsgtk_theme_set_name(NULL);
}
while (current) {
nsgtk_theme_implement(current);
current = nsgtk_scaffolding_iterate(current);
}
END_HANDLER
BUTTON_CLICKED(buttonaddtheme)
char *filename, *directory;
size_t len;
GtkWidget *fc = gtk_file_chooser_dialog_new(
messages_get("gtkAddThemeTitle"),
GTK_WINDOW(wndPreferences),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
len = SLEN("themes") + strlen(res_dir_location) + 1;
char themesfolder[len];
snprintf(themesfolder, len, "%sthemes", res_dir_location);
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc),
themesfolder);
gint res = gtk_dialog_run(GTK_DIALOG(fc));
if (res == GTK_RESPONSE_ACCEPT) {
filename = gtk_file_chooser_get_current_folder(
GTK_FILE_CHOOSER(fc));
if (strcmp(filename, themesfolder) != 0) {
directory = strrchr(filename, '/');
*directory = '\0';
if (strcmp(filename, themesfolder) != 0) {
warn_user(messages_get(
"gtkThemeFolderInstructions"),
0);
gtk_widget_destroy(GTK_WIDGET(fc));
free(filename);
free(themesfolder);
return FALSE;
} else {
directory++;
}
} else {
free(filename);
filename = gtk_file_chooser_get_filename(
GTK_FILE_CHOOSER(fc));
if (strcmp(filename, themesfolder) == 0) {
warn_user(messages_get("gtkThemeFolderSub"),
0);
gtk_widget_destroy(GTK_WIDGET(fc));
free(filename);
free(themesfolder);
return FALSE;
}
directory = strrchr(filename, '/') + 1;
}
gtk_widget_destroy(GTK_WIDGET(fc));
nsgtk_theme_add(directory);
free(filename);
}
END_HANDLER
CHECK_CHANGED(sourceButtonTab, option_source_tab)
END_HANDLER
SPIN_CHANGED(spinMarginTop, option_margin_top)
END_HANDLER

View File

@ -1,5 +1,6 @@
/*
* Copyright 2006 Rob Kendrick <rjek@rjek.com>
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -23,8 +24,11 @@
extern GtkDialog *wndPreferences;
GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent); /** Init options and load window */
GtkDialog* nsgtk_options_init(struct browser_window *bw, GtkWindow *parent);
/** Init options and load window */
void nsgtk_options_load(void); /** Load current options into window */
void nsgtk_options_save(void); /** Save options from window */
bool nsgtk_options_combo_theme_add(const char *themename);
/** add new theme name to combo */
#endif

View File

@ -28,8 +28,10 @@
#include "gtk/gtk_gui.h"
#include "gtk/gtk_print.h"
#include "gtk/gtk_selection.h"
#include "gtk/options.h"
#include "desktop/netsurf.h"
#include "desktop/print.h"
#include "desktop/options.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
@ -57,10 +59,10 @@ struct menu_events {
};
static GladeXML *glade_File;
static gchar *glade_Location;
static struct nsgtk_source_window *nsgtk_source_list = 0;
static char source_zoomlevel = 10;
void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw);
static void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g);
static gboolean nsgtk_source_delete_event(GtkWindow *window, gpointer g);
static gboolean nsgtk_source_destroy_event(GtkWindow *window, gpointer g);
@ -102,112 +104,153 @@ MENUEVENT(source_about),
};
void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
{
if (bw->current_content->type == CONTENT_HTML) {
glade_Location = g_strconcat(res_dir_location, "source.glade",
NULL);
glade_File = glade_xml_new(glade_Location, NULL, NULL);
if (glade_File == NULL) {
LOG(("error loading glade tree"));
}
char *data = NULL;
utf8_convert_ret r = utf8_from_enc(
bw->current_content->source_data,
bw->current_content->data.html.encoding,
bw->current_content->source_size,
&data);
if (r == UTF8_CONVERT_NOMEM) {
warn_user("NoMemory",0);
return;
} else if (r == UTF8_CONVERT_BADENC) {
warn_user("EncNotRec",0);
return;
}
GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget(
glade_File, "wndSource"));
GtkWidget *cutbutton = glade_xml_get_widget(
glade_File, "source_cut");
GtkWidget *pastebutton = glade_xml_get_widget(
glade_File, "source_paste");
GtkWidget *deletebutton = glade_xml_get_widget(
glade_File, "source_delete");
GtkWidget *printbutton = glade_xml_get_widget(
glade_File, "source_print");
gtk_widget_set_sensitive(cutbutton, FALSE);
gtk_widget_set_sensitive(pastebutton, FALSE);
gtk_widget_set_sensitive(deletebutton, FALSE);
/* for now */
gtk_widget_set_sensitive(printbutton, FALSE);
struct nsgtk_source_window *thiswindow =
malloc(sizeof(struct nsgtk_source_window));
if (thiswindow == NULL) {
free(data);
warn_user("NoMemory", 0);
return;
}
thiswindow->url = strdup(bw->current_content->url);
if (thiswindow->url == NULL) {
free(thiswindow);
free(data);
warn_user("NoMemory", 0);
return;
}
thiswindow->data = data;
thiswindow->sourcewindow = wndSource;
thiswindow->bw = bw;
{
char glade_Location[strlen(res_dir_location) + SLEN("source.glade")
+ 1];
if (bw->current_content->type != CONTENT_HTML)
return;
char *title = malloc(strlen(bw->current_content->url)
+ SLEN("Source of ") + 1);
if (title == NULL) {
free(thiswindow->url);
free(thiswindow);
free(data);
warn_user("NoMemory", 0);
if (option_source_tab) {
nsgtk_source_tab_init(parent, bw);
return;
}
sprintf(glade_Location, "%ssource.glade", res_dir_location);
glade_File = glade_xml_new(glade_Location, NULL, NULL);
if (glade_File == NULL) {
LOG(("error loading glade tree"));
}
char *data = NULL;
utf8_convert_ret r = utf8_from_enc(
bw->current_content->source_data,
bw->current_content->data.html.encoding,
bw->current_content->source_size,
&data);
if (r == UTF8_CONVERT_NOMEM) {
warn_user("NoMemory",0);
return;
} else if (r == UTF8_CONVERT_BADENC) {
warn_user("EncNotRec",0);
return;
}
GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget(
glade_File, "wndSource"));
GtkWidget *cutbutton = glade_xml_get_widget(
glade_File, "source_cut");
GtkWidget *pastebutton = glade_xml_get_widget(
glade_File, "source_paste");
GtkWidget *deletebutton = glade_xml_get_widget(
glade_File, "source_delete");
GtkWidget *printbutton = glade_xml_get_widget(
glade_File, "source_print");
gtk_widget_set_sensitive(cutbutton, FALSE);
gtk_widget_set_sensitive(pastebutton, FALSE);
gtk_widget_set_sensitive(deletebutton, FALSE);
/* for now */
gtk_widget_set_sensitive(printbutton, FALSE);
struct nsgtk_source_window *thiswindow =
malloc(sizeof(struct nsgtk_source_window));
if (thiswindow == NULL) {
free(data);
warn_user("NoMemory", 0);
return;
}
thiswindow->url = strdup(bw->current_content->url);
if (thiswindow->url == NULL) {
free(thiswindow);
free(data);
warn_user("NoMemory", 0);
return;
}
thiswindow->data = data;
thiswindow->sourcewindow = wndSource;
thiswindow->bw = bw;
char title[strlen(bw->current_content->url) + SLEN("Source of ") + 1];
sprintf(title, "Source of %s", bw->current_content->url);
thiswindow->next = nsgtk_source_list;
thiswindow->prev = NULL;
if (nsgtk_source_list != NULL)
nsgtk_source_list->prev = thiswindow;
nsgtk_source_list = thiswindow;
nsgtk_attach_source_menu_handlers(glade_File, thiswindow);
gtk_window_set_title(wndSource, title);
g_signal_connect(G_OBJECT(wndSource), "destroy",
G_CALLBACK(nsgtk_source_destroy_event),
thiswindow);
g_signal_connect(G_OBJECT(wndSource), "delete-event",
G_CALLBACK(nsgtk_source_delete_event),
thiswindow);
GtkTextView *sourceview = GTK_TEXT_VIEW(
glade_xml_get_widget(glade_File,
"source_view"));
PangoFontDescription *fontdesc =
pango_font_description_from_string("Monospace 8");
thiswindow->gv = sourceview;
gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc);
GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview);
gtk_text_buffer_set_text(tb, thiswindow->data, -1);
gtk_widget_show(GTK_WIDGET(wndSource));
}
void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw)
{
char *ndata = 0;
utf8_convert_ret r = utf8_from_enc(
bw->current_content->source_data,
bw->current_content->data.html.encoding,
bw->current_content->source_size,
&ndata);
if (r == UTF8_CONVERT_NOMEM) {
warn_user("NoMemory",0);
return;
} else if (r == UTF8_CONVERT_BADENC) {
warn_user("EncNotRec",0);
return;
}
gchar *filename;
char *fileurl;
gint handle = g_file_open_tmp("nsgtksourceXXXXXX", &filename, NULL);
close (handle); /* in case it was binary mode */
FILE *f = fopen(filename, "w");
fprintf(f, "%s", ndata);
fclose(f);
free(ndata);
fileurl = path_to_url(filename);
g_free(filename);
if (fileurl == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
struct browser_window *newbw = browser_window_create(fileurl, bw,
NULL, false, true);
free(fileurl);
if (newbw->current_content) {
newbw->current_content->title = malloc(
strlen(bw->current_content->url) +
SLEN("source of ") + 1);
if (newbw->current_content->title == NULL)
return;
}
sprintf(title, "Source of %s", bw->current_content->url);
thiswindow->next = nsgtk_source_list;
thiswindow->prev = NULL;
if (nsgtk_source_list != NULL)
nsgtk_source_list->prev = thiswindow;
nsgtk_source_list = thiswindow;
nsgtk_attach_source_menu_handlers(glade_File, thiswindow);
gtk_window_set_title(wndSource, title);
g_signal_connect(G_OBJECT(wndSource), "destroy",
G_CALLBACK(nsgtk_source_destroy_event),
thiswindow);
g_signal_connect(G_OBJECT(wndSource), "delete-event",
G_CALLBACK(nsgtk_source_delete_event),
thiswindow);
GtkTextView *sourceview = GTK_TEXT_VIEW(
glade_xml_get_widget(glade_File,
"source_view"));
PangoFontDescription *fontdesc =
pango_font_description_from_string("Monospace 8");
thiswindow->gv = sourceview;
gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc);
GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview);
gtk_text_buffer_set_text(tb, thiswindow->data, -1);
gtk_widget_show(GTK_WIDGET(wndSource));
free(title);
sprintf(newbw->current_content->title, "source of %s",
bw->current_content->url);
}
}
void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g)
{
struct menu_events *event = source_menu_events;
@ -264,7 +307,7 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename,
{
FILE *f;
bool auth = true;
char temp[15];
char temp[255];
GtkWidget *notif, *label;
if (!(access(filename, F_OK))) {
@ -277,21 +320,18 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
char *warn;
const char *format = messages_get("gtkOverwrite");
int len = strlen(filename) + strlen(format);
int len = strlen(filename) + strlen(format) + SLEN("\n\n") + 1;
char warn[len];
auth = false;
warn = malloc(len);
if (warn == NULL) {
warn_user("NoMemory", 0);
return;
}
warn[0] = '\n';
snprintf(warn + 1, len - 2, format, filename);
len = strlen(warn);
warn[len - 1] = '\n';
warn[len] = '\0';
snprintf(warn, len, format, filename);
label = gtk_label_new(g_strconcat("\n",warn,"\n", NULL));
label = gtk_label_new(warn);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(confd)->vbox),
label);
gtk_widget_show(label);
@ -299,16 +339,19 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename,
auth = true;
}
gtk_widget_destroy(confd);
free(warn);
}
if (auth) {
f = fopen(filename, "w+");
fprintf(f, "%s", data);
fclose(f);
strcpy(temp, messages_get("gtkSaveConfirm"));
snprintf(temp, sizeof(temp), "\n %s"
" \n",
messages_get("gtkSaveConfirm"));
} else {
strcpy(temp, messages_get("gtkSaveCancelled"));
snprintf(temp, sizeof(temp), "\n %s"
" \n",
messages_get("gtkSaveCancelled"));
}
notif = gtk_dialog_new_with_buttons(temp,
@ -316,8 +359,7 @@ void nsgtk_source_file_save(GtkWindow *parent, const char *filename,
GTK_RESPONSE_NONE, NULL);
g_signal_connect_swapped(notif, "response",
G_CALLBACK(gtk_widget_destroy), notif);
label = gtk_label_new(g_strconcat("\n ", temp,
" \n", NULL));
label = gtk_label_new(temp);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(notif)->vbox), label);
gtk_widget_show_all(notif);
}

View File

@ -33,6 +33,7 @@
#include "gtk/gtk_scaffolding.h"
#include "gtk/options.h"
#include "gtk/gtk_download.h"
#include "gtk/gtk_window.h"
#define UPDATE_RATE 500 /* In milliseconds */
#define GLADE_NAME "downloads.glade"
@ -86,9 +87,9 @@ static gboolean nsgtk_download_handle_error (GError *error);
void nsgtk_download_init()
{
gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL);
char glade_location[strlen(res_dir_location) + SLEN(GLADE_NAME) + 1];
sprintf(glade_location, "%s" GLADE_NAME, res_dir_location);
GladeXML *gladeFile = glade_xml_new(glade_location, NULL, NULL);
g_free(glade_location);
nsgtk_download_buttons =
glade_xml_get_widget_prefix(gladeFile, "button");
@ -202,11 +203,12 @@ struct gui_download_window *gui_download_window_create(const char *url,
gchar *filename;
gchar *destination;
gboolean unknown_size = total_size == 0;
const gchar *size = (total_size == 0 ?
const char *size = (total_size == 0 ?
messages_get("gtkUnknownSize") :
human_friendly_bytesize(total_size));
nsgtk_download_parent = nsgtk_scaffolding_get_window(gui);
nsgtk_download_parent = nsgtk_scaffolding_window(nsgtk_get_scaffold(
gui));
struct gui_download_window *download = malloc(sizeof *download);
if (url_nice(url, &filename, false) != URL_FUNC_OK)
@ -488,8 +490,9 @@ gboolean nsgtk_download_update(gboolean force_update)
void nsgtk_download_store_update_item (struct gui_download_window *dl)
{
gchar *info = nsgtk_download_info_to_string(dl);
gchar *speed = g_strconcat(human_friendly_bytesize(dl->speed), "/s",
NULL);
char *human = human_friendly_bytesize(dl->speed);
char speed[strlen(human) + SLEN("/s") + 1];
sprintf(speed, "%s/s", human);
gchar *time = nsgtk_download_time_to_string(dl->time_remaining);
gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING;
@ -508,7 +511,6 @@ void nsgtk_download_store_update_item (struct gui_download_window *dl)
-1);
g_free(info);
g_free(speed);
g_free(time);
}
@ -634,7 +636,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain,
{
enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS };
GtkWidget *dialog;
gchar *destination = NULL;
char *destination = NULL;
gchar *message = g_strdup(messages_get("gtkStartDownload"));
gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename,
domain, size);
@ -682,9 +684,15 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain,
break;
}
case GTK_RESPONSE_DOWNLOAD: {
destination = g_strconcat(option_downloads_directory,
"/", filename, NULL);
/* Test if file already exists and display overwrite
destination = malloc(strlen(option_downloads_directory)
+ strlen(filename) + SLEN("/") + 1);
if (destination == NULL) {
warn_user(messages_get("NoMemory"), 0);
break;
}
sprintf(destination, "%s/%s",
option_downloads_directory, filename);
/* Test if file already exists and display overwrite
* confirmation if needed */
if (g_file_test(destination, G_FILE_TEST_EXISTS)
&& option_request_overwrite) {
@ -711,7 +719,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain,
gtk_button_set_image(GTK_BUTTON(button),
gtk_image_new_from_stock(
"gtk-save",
GTK_ICON_SIZE_BUTTON));
GTK_ICON_SIZE_BUTTON));
gint result = gtk_dialog_run(GTK_DIALOG(
dialog));

View File

@ -43,6 +43,7 @@
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "desktop/save_pdf/pdf_plotters.h"
#include "desktop/searchweb.h"
#include "desktop/textinput.h"
#include "gtk/gtk_gui.h"
#include "gtk/dialogs/gtk_options.h"
@ -68,15 +69,23 @@ char *default_stylesheet_url;
char *quirks_stylesheet_url;
char *adblock_stylesheet_url;
char *options_file_location;
char *glade_file_location;
char *glade_netsurf_file_location;
char *glade_password_file_location;
char *glade_warning_file_location;
char *glade_login_file_location;
char *glade_ssl_file_location;
char *glade_toolbar_file_location;
char *toolbar_indices_file_location;
char *res_dir_location;
char *print_options_file_location;
struct gui_window *search_current_window = 0;
GtkWindow *wndAbout;
GtkWindow *wndWarning;
GladeXML *gladeWindows;
GladeXML *gladeNetsurf;
GladeXML *gladePassword;
GladeXML *gladeWarning;
GladeXML *gladeLogin;
GladeXML *gladeSsl;
GtkWindow *wndTooltip;
GtkLabel *labelTooltip;
@ -195,12 +204,28 @@ void gui_init(int argc, char** argv)
check_homedir();
find_resource(buf, "netsurf.glade", "./gtk/res/netsurf.glade");
LOG(("Using '%s' as Glade template file", buf));
glade_file_location = strdup(buf);
LOG(("Using '%s' as Netsurf glade template file", buf));
glade_netsurf_file_location = strdup(buf);
buf[strlen(buf)- 13] = 0;
LOG(("Using '%s' as Resources directory", buf));
res_dir_location = strdup(buf);
find_resource(buf, "password.glade", "./gtk/res/password.glade");
LOG(("Using '%s' as password glade template file", buf));
glade_password_file_location = strdup(buf);
find_resource(buf, "warning.glade", "./gtk/res/warning.glade");
LOG(("Using '%s' as warning glade template file", buf));
glade_warning_file_location = strdup(buf);
find_resource(buf, "login.glade", "./gtk/res/login.glade");
LOG(("Using '%s' as login glade template file", buf));
glade_login_file_location = strdup(buf);
find_resource(buf, "ssl.glade", "./gtk/res/ssl.glade");
LOG(("Using '%s' as ssl glade template file", buf));
glade_ssl_file_location = strdup(buf);
find_resource(buf, "Aliases", "./gtk/res/Aliases");
LOG(("Using '%s' as Aliases file", buf));
@ -208,17 +233,42 @@ void gui_init(int argc, char** argv)
die("Unable to initialise HTML parsing library.\n");
glade_init();
gladeWindows = glade_xml_new(glade_file_location, NULL, NULL);
if (gladeWindows == NULL)
die("Unable to load Glade window definitions.\n");
glade_xml_signal_autoconnect(gladeWindows);
gladeWarning = glade_xml_new(glade_warning_file_location, NULL, NULL);
if (gladeWarning == NULL)
die("Unable to load glade warning window definitions.\n");
glade_xml_signal_autoconnect(gladeWarning);
gladeNetsurf = glade_xml_new(glade_netsurf_file_location, NULL, NULL);
if (gladeNetsurf == NULL)
die("Unable to load glade Netsurf window definitions.\n");
glade_xml_signal_autoconnect(gladeNetsurf);
gladePassword = glade_xml_new(glade_password_file_location, NULL, NULL);
if (gladePassword == NULL)
die("Unable to load glade password window definitions.\n");
glade_xml_signal_autoconnect(gladePassword);
gladeLogin = glade_xml_new(glade_login_file_location, NULL, NULL);
if (gladeLogin == NULL)
die("Unable to load glade login window definitions.\n");
glade_xml_signal_autoconnect(gladeLogin);
gladeSsl = glade_xml_new(glade_ssl_file_location, NULL, NULL);
if (gladeSsl == NULL)
die("Unable to load glade ssl window definitions.\n");
glade_xml_signal_autoconnect(gladeSsl);
find_resource(buf, "toolbar.glade", "./gtk/res/toolbar.glade");
LOG(("Using '%s' as glade toolbar file", buf));
glade_toolbar_file_location = strdup(buf);
find_resource(buf, "netsurf.xpm", "./gtk/res/netsurf.xpm");
gtk_window_set_default_icon_from_file(buf, NULL);
wndTooltip = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndTooltip"));
labelTooltip = GTK_LABEL(glade_xml_get_widget(gladeWindows, "tooltip"));
/* superfluous ? */
wndTooltip = GTK_WINDOW(glade_xml_get_widget(gladeNetsurf, "wndTooltip"));
labelTooltip = GTK_LABEL(glade_xml_get_widget(gladeNetsurf, "tooltip"));
nsgtk_completion_init();
/* This is an ugly hack to just get the new-style throbber going.
@ -321,12 +371,25 @@ void gui_init(int argc, char** argv)
LOG(("Using '%s' as Print Settings file", buf));
print_options_file_location = strdup(buf);
find_resource(buf, "SearchEngines", "./gtk/res/SearchEngines");
LOG(("Using '%s' as Search Engines file", buf));
search_engines_file_location = strdup(buf);
find_resource(buf, "default.ico", "./gtk/res/default.ico");
LOG(("Using '%s' as default search ico", buf));
search_default_ico_location = strdup(buf);
find_resource(buf, "toolbarIndices", "./gtk/res/toolbarIndices");
LOG(("Using '%s' as custom toolbar settings file", buf));
toolbar_indices_file_location = strdup(buf);
urldb_load(option_url_file);
urldb_load_cookies(option_cookie_file);
/* superfluous ? */
wndAbout = GTK_WINDOW(glade_xml_get_widget(gladeNetsurf, "wndAbout"));
wndAbout = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndAbout"));
wndWarning = GTK_WINDOW(glade_xml_get_widget(gladeWindows, "wndWarning"));
wndWarning = GTK_WINDOW(glade_xml_get_widget(gladeWarning, "wndWarning"));
nsgtk_history_init();
nsgtk_download_init();
@ -428,6 +491,9 @@ void gui_quit(void)
free(option_cookie_file);
free(option_cookie_jar);
free(print_options_file_location);
free(search_engines_file_location);
free(search_default_ico_location);
free(toolbar_indices_file_location);
gtk_fetch_filetype_fin();
/* We don't care if this fails as we're about to die, anyway */
hubbub_finalise(myrealloc, NULL);
@ -490,15 +556,6 @@ void gui_launch_url(const char *url)
{
}
bool gui_search_term_highlighted(struct gui_window *g,
unsigned start_offset, unsigned end_offset,
unsigned *start_idx, unsigned *end_idx)
{
return false;
}
void warn_user(const char *warning, const char *detail)
{
char buf[300]; /* 300 is the size the RISC OS GUI uses */
@ -510,7 +567,7 @@ void warn_user(const char *warning, const char *detail)
detail ? detail : "");
buf[sizeof(buf) - 1] = 0;
gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWindows, "labelWarning")), buf);
gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gladeWarning, "labelWarning")), buf);
gtk_widget_show_all(GTK_WIDGET(wndWarning));
}
@ -536,7 +593,7 @@ static void nsgtk_create_ssl_verify_window(struct browser_window *bw,
struct content *c, const struct ssl_cert_info *certs,
unsigned long num)
{
GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL);
GladeXML *x = glade_xml_new(glade_ssl_file_location, NULL, NULL);
GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndSSLProblem"));
GtkButton *accept, *reject;
void **session = calloc(sizeof(void *), 4);
@ -618,7 +675,7 @@ utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len,
char *path_to_url(const char *path)
{
char *r = malloc(strlen(path) + 7 + 1);
char *r = malloc(strlen(path) + SLEN("file://") + 1);
strcpy(r, "file://");
strcat(r, path);
@ -640,7 +697,7 @@ bool cookies_update(const char *domain, const struct cookie_data *data)
void PDF_Password(char **owner_pass, char **user_pass, char *path)
{
GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL);
GladeXML *x = glade_xml_new(glade_password_file_location, NULL, NULL);
GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndPDFPassword"));
GtkButton *ok, *no;
void **data = malloc(5 * sizeof(void *));

View File

@ -25,8 +25,18 @@
#include <glade/glade.h>
extern bool gui_in_multitask;
extern GladeXML *gladeWindows;
extern char *glade_file_location;
extern GladeXML *gladeNetsurf;
extern GladeXML *gladePassword;
extern GladeXML *gladeWarning;
extern GladeXML *gladeLogin;
extern GladeXML *gladeSsl;
extern char *glade_netsurf_file_location;
extern char *glade_password_file_location;
extern char *glade_warning_file_location;
extern char *glade_login_file_location;
extern char *glade_ssl_file_location;
extern char *glade_toolbar_file_location;
extern char *toolbar_indices_file_location;
extern char *options_file_location;
extern char *res_dir_location;
extern char *print_options_file_location;

View File

@ -107,9 +107,9 @@ void nsgtk_history_init(void)
dateAt = messages_get("DateAt");
domainAll = messages_get("DomainAll");
gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL);
char glade_location[strlen(res_dir_location) + SLEN(GLADE_NAME) + 1];
sprintf(glade_location, "%s" GLADE_NAME, res_dir_location);
gladeFile = glade_xml_new(glade_location, NULL, NULL);
g_free(glade_location);
glade_xml_signal_autoconnect(gladeFile);
wndHistory = GTK_WINDOW(glade_xml_get_widget(gladeFile,
@ -500,23 +500,23 @@ void nsgtk_history_search_clear (GtkEntry *entry)
gchar *nsgtk_history_date_parse(time_t visit_time)
{
gchar *date_string = malloc(30);
gchar format[30];
char *date_string = malloc(30);
char format[30];
time_t current_time = time(NULL);
gint current_day = localtime(&current_time)->tm_yday;
int current_day = localtime(&current_time)->tm_yday;
struct tm *visit_date = localtime(&visit_time);
if (visit_date->tm_yday == current_day)
g_snprintf(format, 30, "%s %s %%I:%%M %%p",
snprintf(format, 30, "%s %s %%I:%%M %%p",
dateToday, dateAt);
else if (current_day - visit_date->tm_yday == 1)
g_snprintf(format, 30, "%s %s %%I:%%M %%p",
snprintf(format, 30, "%s %s %%I:%%M %%p",
dateYesterday, dateAt);
else if (current_day - visit_date->tm_yday < 7)
g_snprintf(format, 30, "%%A %s %%I:%%M %%p",
snprintf(format, 30, "%%A %s %%I:%%M %%p",
dateAt);
else
g_snprintf(format, 30, "%%B %%d, %%Y");
snprintf(format, 30, "%%B %%d, %%Y");
strftime(date_string, 30, format, visit_date);

View File

@ -74,7 +74,7 @@ void create_login_window(struct browser_window *bw, const char *host,
* the widgets we're interested in.
*/
GladeXML *x = glade_xml_new(glade_file_location, NULL, NULL);
GladeXML *x = glade_xml_new(glade_login_file_location, NULL, NULL);
GtkWindow *wnd = GTK_WINDOW(glade_xml_get_widget(x, "wndLogin"));
GtkLabel *lhost, *lrealm;
GtkEntry *euser, *epass;

422
gtk/gtk_menu.c Normal file
View File

@ -0,0 +1,422 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include "gtk/gtk_menu.h"
#include "utils/messages.h"
#include "utils/utils.h"
static struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *);
static struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu(
GtkAccelGroup *);
static struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *);
static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
GtkAccelGroup *);
static struct nsgtk_debugging_submenu *nsgtk_menu_debugging_submenu(
GtkAccelGroup *);
static bool nsgtk_menu_add_image_item(GtkMenu *menu,
GtkImageMenuItem **item, const char *message,
const char *messageAccel, GtkAccelGroup *group);
/**
* adds image menu item to specified menu
* \param menu the menu to add the item to
* \param item a pointer to the item's location in the menu struct
* \param message the menu item I18n lookup value
* \param messageAccel the menu item accelerator I18n lookup value
* \param group the 'global' in a gtk sense accelerator group
*/
bool nsgtk_menu_add_image_item(GtkMenu *menu,
GtkImageMenuItem **item, const char *message,
const char *messageAccel, GtkAccelGroup *group)
{
unsigned int key;
GdkModifierType mod;
*item = GTK_IMAGE_MENU_ITEM(gtk_image_menu_item_new_with_mnemonic(
messages_get(message)));
if (*item == NULL)
return false;
gtk_accelerator_parse(messages_get(messageAccel), &key, &mod);
if (key > 0)
gtk_widget_add_accelerator(GTK_WIDGET(*item), "activate",
group, key, mod, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(*item));
gtk_widget_show(GTK_WIDGET(*item));
return true;
}
#define IMAGE_ITEM(p, q, r, s, t)\
nsgtk_menu_add_image_item(s->p##_menu, &(s->q##_menuitem), #r,\
#r "Accel", t);
#define CHECK_ITEM(p, q, r, s)\
s->q##_menuitem = GTK_CHECK_MENU_ITEM(\
gtk_check_menu_item_new_with_mnemonic(\
messages_get(#r)));\
if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) {\
gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu),\
GTK_WIDGET(s->q##_menuitem));\
gtk_widget_show(GTK_WIDGET(s->q##_menuitem));\
}
#define SET_SUBMENU(q, r)\
r->q##_submenu = nsgtk_menu_##q##_submenu(group);\
if ((r->q##_submenu != NULL) && (r->q##_submenu->q##_menu != NULL) && \
(r->q##_menuitem != NULL)) {\
gtk_menu_item_set_submenu(GTK_MENU_ITEM(r->q##_menuitem),\
GTK_WIDGET(r->q##_submenu->q##_menu));\
}
#define ADD_SEP(q, r)\
w = gtk_separator_menu_item_new();\
if ((w != NULL) && (r->q##_menu != NULL)) {\
gtk_menu_shell_append(GTK_MENU_SHELL(r->q##_menu), w);\
gtk_widget_show(w);\
}
/**
* creates the a file menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_file_menu *nsgtk_menu_file_menu(GtkAccelGroup *group)
{
GtkWidget *w;
struct nsgtk_file_menu *ret = malloc(sizeof(struct nsgtk_file_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->file_menu = GTK_MENU(gtk_menu_new());
if (ret->file_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(file, newwindow, gtkNewWindow, ret, group)
IMAGE_ITEM(file, newtab, gtkNewTab, ret, group)
IMAGE_ITEM(file, openfile, gtkOpenFile, ret, group)
IMAGE_ITEM(file, closewindow, gtkCloseWindow, ret, group)
ADD_SEP(file, ret)
IMAGE_ITEM(file, savepage, gtkSavePage, ret, group)
IMAGE_ITEM(file, export, gtkExport, ret, group)
ADD_SEP(file, ret)
IMAGE_ITEM(file, printpreview, gtkPrintPreview, ret, group)
IMAGE_ITEM(file, print, gtkPrint, ret, group)
ADD_SEP(file, ret)
IMAGE_ITEM(file, quit, gtkQuitMenu, ret, group)
SET_SUBMENU(export, ret)
return ret;
}
/**
* creates an edit menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_edit_menu *nsgtk_menu_edit_menu(GtkAccelGroup *group)
{
GtkWidget *w;
struct nsgtk_edit_menu *ret = malloc(sizeof(struct nsgtk_edit_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->edit_menu = GTK_MENU(gtk_menu_new());
if (ret->edit_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(edit, cut, gtkCut, ret, group)
IMAGE_ITEM(edit, copy, gtkCopy, ret, group)
IMAGE_ITEM(edit, paste, gtkPaste, ret, group)
IMAGE_ITEM(edit, delete, gtkDelete, ret, group)
ADD_SEP(edit, ret)
IMAGE_ITEM(edit, selectall, gtkSelectAll, ret, group)
ADD_SEP(edit, ret)
IMAGE_ITEM(edit, find, gtkFind, ret, group)
ADD_SEP(edit, ret)
IMAGE_ITEM(edit, preferences, gtkPreferences, ret, group)
return ret;
}
/**
* creates a view menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_view_menu *nsgtk_menu_view_menu(GtkAccelGroup *group)
{
GtkWidget *w;
struct nsgtk_view_menu *ret = malloc(sizeof(struct nsgtk_view_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->view_menu = GTK_MENU(gtk_menu_new());
if (ret->view_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(view, stop, gtkStop, ret, group)
IMAGE_ITEM(view, reload, gtkReload, ret, group)
ADD_SEP(view, ret)
IMAGE_ITEM(view, scaleview, gtkScaleView, ret, group)
IMAGE_ITEM(view, fullscreen, gtkFullScreen, ret, group)
IMAGE_ITEM(view, viewsource, gtkViewSource, ret, group)
ADD_SEP(view, ret)
IMAGE_ITEM(view, images, gtkImages, ret, group)
IMAGE_ITEM(view, toolbars, gtkToolbars, ret, group)
ADD_SEP(view, ret)
IMAGE_ITEM(view, downloads, gtkDownloads, ret, group)
IMAGE_ITEM(view, savewindowsize, gtkSaveWindowSize, ret, group)
IMAGE_ITEM(view, debugging, gtkDebugging, ret, group)
SET_SUBMENU(scaleview, ret)
SET_SUBMENU(images, ret)
SET_SUBMENU(toolbars, ret)
SET_SUBMENU(debugging, ret)
return ret;
}
/**
* creates a nav menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group)
{
GtkWidget *w;
struct nsgtk_nav_menu *ret = malloc(sizeof(struct nsgtk_nav_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->nav_menu = GTK_MENU(gtk_menu_new());
if (ret->nav_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(nav, back, gtkBack, ret, group)
IMAGE_ITEM(nav, forward, gtkForward, ret, group)
IMAGE_ITEM(nav, home, gtkHome, ret, group)
ADD_SEP(nav, ret)
IMAGE_ITEM(nav, localhistory, gtkLocalHistory, ret, group)
IMAGE_ITEM(nav, globalhistory, gtkGlobalHistory, ret, group)
ADD_SEP(nav, ret)
IMAGE_ITEM(nav, addbookmarks, gtkAddBookMarks, ret, group)
IMAGE_ITEM(nav, showbookmarks, gtkShowBookMarks, ret, group)
ADD_SEP(nav, ret)
IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group)
return ret;
}
/**
* creates a tabs menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_tabs_menu *nsgtk_menu_tabs_menu(GtkAccelGroup *group)
{
struct nsgtk_tabs_menu *ret = malloc(sizeof(struct nsgtk_tabs_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->tabs_menu = GTK_MENU(gtk_menu_new());
if (ret->tabs_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(tabs, nexttab, gtkNextTab, ret, group)
IMAGE_ITEM(tabs, prevtab, gtkPrevTab, ret, group)
IMAGE_ITEM(tabs, closetab, gtkCloseTab, ret, group)
return ret;
}
/**
* creates a help menu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_help_menu *nsgtk_menu_help_menu(GtkAccelGroup *group)
{
GtkWidget *w;
struct nsgtk_help_menu *ret = malloc(sizeof(struct nsgtk_help_menu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->help_menu = GTK_MENU(gtk_menu_new());
if (ret->help_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(help, contents, gtkContents, ret, group)
IMAGE_ITEM(help, guide, gtkGuide, ret, group)
IMAGE_ITEM(help, info, gtkUserInformation, ret, group)
ADD_SEP(help, ret)
IMAGE_ITEM(help, about, gtkAbout, ret, group)
return ret;
}
/**
* creates an export submenu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *group)
{
struct nsgtk_export_submenu *ret = malloc(sizeof(struct
nsgtk_export_submenu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->export_menu = GTK_MENU(gtk_menu_new());
if (ret->export_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(export, plaintext, gtkPlainText, ret, group)
IMAGE_ITEM(export, drawfile, gtkDrawFile, ret, group)
IMAGE_ITEM(export, postscript, gtkPostScript, ret, group)
IMAGE_ITEM(export, pdf, gtkPDF, ret, group)
return ret;
}
/**
* creates a scaleview submenu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu(
GtkAccelGroup *group)
{
struct nsgtk_scaleview_submenu *ret =
malloc(sizeof(struct nsgtk_scaleview_submenu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->scaleview_menu = GTK_MENU(gtk_menu_new());
if (ret->scaleview_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(scaleview, zoomplus, gtkZoomPlus, ret, group)
IMAGE_ITEM(scaleview, zoomnormal, gtkZoomNormal, ret, group)
IMAGE_ITEM(scaleview, zoomminus, gtkZoomMinus, ret, group)
return ret;
}
/**
* creates an images submenu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *group)
{
struct nsgtk_images_submenu *ret =
malloc(sizeof(struct nsgtk_images_submenu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->images_menu = GTK_MENU(gtk_menu_new());
if (ret->images_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
CHECK_ITEM(images, foregroundimages, gtkForegroundImages, ret)
CHECK_ITEM(images, backgroundimages, gtkBackgroundImages, ret)
return ret;
}
/**
* creates a toolbars submenu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
GtkAccelGroup *group)
{
struct nsgtk_toolbars_submenu *ret =
malloc(sizeof(struct nsgtk_toolbars_submenu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->toolbars_menu = GTK_MENU(gtk_menu_new());
if (ret->toolbars_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
CHECK_ITEM(toolbars, menubar, gtkMenuBar, ret)
if (ret->menubar_menuitem != NULL)
gtk_check_menu_item_set_active(ret->menubar_menuitem, TRUE);
CHECK_ITEM(toolbars, toolbar, gtkToolBar, ret)
if (ret->toolbar_menuitem != NULL)
gtk_check_menu_item_set_active(ret->toolbar_menuitem, TRUE);
CHECK_ITEM(toolbars, statusbar, gtkStatusBar, ret)
if (ret->statusbar_menuitem != NULL)
gtk_check_menu_item_set_active(ret->statusbar_menuitem, TRUE);
return ret;
}
/**
* creates a debugging submenu
* \param group the 'global' in a gtk sense accelerator reference
*/
struct nsgtk_debugging_submenu *nsgtk_menu_debugging_submenu(
GtkAccelGroup *group)
{
struct nsgtk_debugging_submenu *ret =
malloc(sizeof(struct nsgtk_debugging_submenu));
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
ret->debugging_menu = GTK_MENU(gtk_menu_new());
if (ret->debugging_menu == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
IMAGE_ITEM(debugging, toggledebugging, gtkToggleDebugging, ret, group)
IMAGE_ITEM(debugging, saveboxtree, gtkSaveBoxTree, ret, group)
IMAGE_ITEM(debugging, savedomtree, gtkSaveDomTree, ret, group)
return ret;
}
#undef CHECK_ITEM
#undef IMAGE_ITEM
#undef SET_SUBMENU
#undef ADD_SEP

135
gtk/gtk_menu.h Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_GTK_MENU_H_
#define _NETSURF_GTK_MENU_H_
#include <gtk/gtk.h>
struct nsgtk_file_menu {
GtkMenu *file_menu;
GtkImageMenuItem *newwindow_menuitem;
GtkImageMenuItem *newtab_menuitem;
GtkImageMenuItem *openfile_menuitem;
GtkImageMenuItem *closewindow_menuitem;
GtkImageMenuItem *savepage_menuitem;
GtkImageMenuItem *export_menuitem;
struct nsgtk_export_submenu *export_submenu;
GtkImageMenuItem *printpreview_menuitem;
GtkImageMenuItem *print_menuitem;
GtkImageMenuItem *quit_menuitem;
};
struct nsgtk_edit_menu {
GtkMenu *edit_menu;
GtkImageMenuItem *cut_menuitem;
GtkImageMenuItem *copy_menuitem;
GtkImageMenuItem *paste_menuitem;
GtkImageMenuItem *delete_menuitem;
GtkImageMenuItem *selectall_menuitem;
GtkImageMenuItem *find_menuitem;
GtkImageMenuItem *preferences_menuitem;
};
struct nsgtk_view_menu {
GtkMenu *view_menu;
GtkImageMenuItem *stop_menuitem;
GtkImageMenuItem *reload_menuitem;
GtkImageMenuItem *scaleview_menuitem;
struct nsgtk_scaleview_submenu *scaleview_submenu;
GtkImageMenuItem *fullscreen_menuitem;
GtkImageMenuItem *viewsource_menuitem;
GtkImageMenuItem *images_menuitem;
struct nsgtk_images_submenu *images_submenu;
GtkImageMenuItem *toolbars_menuitem;
struct nsgtk_toolbars_submenu *toolbars_submenu;
GtkImageMenuItem *downloads_menuitem;
GtkImageMenuItem *savewindowsize_menuitem;
GtkImageMenuItem *debugging_menuitem;
struct nsgtk_debugging_submenu *debugging_submenu;
};
struct nsgtk_nav_menu {
GtkMenu *nav_menu;
GtkImageMenuItem *back_menuitem;
GtkImageMenuItem *forward_menuitem;
GtkImageMenuItem *home_menuitem;
GtkImageMenuItem *localhistory_menuitem;
GtkImageMenuItem *globalhistory_menuitem;
GtkImageMenuItem *addbookmarks_menuitem;
GtkImageMenuItem *showbookmarks_menuitem;
GtkImageMenuItem *openlocation_menuitem;
};
struct nsgtk_tabs_menu {
GtkMenu *tabs_menu;
GtkImageMenuItem *nexttab_menuitem;
GtkImageMenuItem *prevtab_menuitem;
GtkImageMenuItem *closetab_menuitem;
};
struct nsgtk_help_menu {
GtkMenu *help_menu;
GtkImageMenuItem *contents_menuitem;
GtkImageMenuItem *guide_menuitem;
GtkImageMenuItem *info_menuitem;
GtkImageMenuItem *about_menuitem;
};
struct nsgtk_export_submenu {
GtkMenu *export_menu;
GtkImageMenuItem *plaintext_menuitem;
GtkImageMenuItem *drawfile_menuitem;
GtkImageMenuItem *postscript_menuitem;
GtkImageMenuItem *pdf_menuitem;
};
struct nsgtk_scaleview_submenu {
GtkMenu *scaleview_menu;
GtkImageMenuItem *zoomplus_menuitem;
GtkImageMenuItem *zoomminus_menuitem;
GtkImageMenuItem *zoomnormal_menuitem;
};
struct nsgtk_images_submenu {
GtkMenu *images_menu;
GtkCheckMenuItem *foregroundimages_menuitem;
GtkCheckMenuItem *backgroundimages_menuitem;
};
struct nsgtk_toolbars_submenu {
GtkMenu *toolbars_menu;
GtkCheckMenuItem *menubar_menuitem;
GtkCheckMenuItem *toolbar_menuitem;
GtkCheckMenuItem *statusbar_menuitem;
};
struct nsgtk_debugging_submenu {
GtkMenu *debugging_menu;
GtkImageMenuItem *toggledebugging_menuitem;
GtkImageMenuItem *saveboxtree_menuitem;
GtkImageMenuItem *savedomtree_menuitem;
};
struct nsgtk_file_menu *nsgtk_menu_file_menu(GtkAccelGroup *group);
struct nsgtk_edit_menu *nsgtk_menu_edit_menu(GtkAccelGroup *group);
struct nsgtk_view_menu *nsgtk_menu_view_menu(GtkAccelGroup *group);
struct nsgtk_nav_menu *nsgtk_menu_nav_menu(GtkAccelGroup *group);
struct nsgtk_tabs_menu *nsgtk_menu_tabs_menu(GtkAccelGroup *group);
struct nsgtk_help_menu *nsgtk_menu_help_menu(GtkAccelGroup *group);
#endif

81
gtk/gtk_save.c Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <libxml/HTMLtree.h>
#include "content/content.h"
#include "desktop/save_complete.h"
#include "utils/utils.h"
/**
* conducts the filesystem save appropriate to the gui
* \param path save path
* \param filename name of file to save
* \param len data length
* \param sourcedata pointer to data to save
* \param type content type
* \return true for success
*/
bool save_complete_gui_save(const char *path, const char *filename,
size_t len, const char *sourcedata, content_type type)
{
int res;
int namelen;
namelen = strlen(path) + strlen(filename) + 2; /* '/', '\0' */
char *fullpath = malloc(namelen);
if (!fullpath) {
warn_user("NoMemory", 0);
return false;
}
snprintf(fullpath, namelen, "%s/%s", path, filename);
FILE *f;
f = fopen(fullpath, "wb");
free(fullpath);
if (f == NULL)
return false;
res = fwrite(sourcedata, len, 1, f);
fclose(f);
if (res != 1)
return false;
return true;
}
/**
* wrapper for lib function htmlSaveFileFormat; front sets path from path
* + filename in a filesystem-specific way
*/
int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
xmlDocPtr cur, const char *encoding, int format)
{
int ret;
int len = strlen(path) + strlen(filename) + 2;
char *fullpath = malloc(len);
if (fullpath == NULL) {
warn_user("NoMemory", 0);
return -1;
}
snprintf(fullpath, len, "%s/%s", path, filename);
ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
free(fullpath);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -21,63 +21,219 @@
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <glib.h>
#include "desktop/gui.h"
#include "desktop/plotters.h"
#include "gtk/gtk_menu.h"
#include "gtk/sexy_icon_entry.h"
typedef struct gtk_scaffolding nsgtk_scaffolding;
struct gtk_scaffolding {
typedef enum {
BACK_BUTTON = 0,
HISTORY_BUTTON,
FORWARD_BUTTON,
STOP_BUTTON,
RELOAD_BUTTON,
HOME_BUTTON,
URL_BAR_ITEM,
WEBSEARCH_ITEM,
THROBBER_ITEM,
NEWWINDOW_BUTTON,
NEWTAB_BUTTON,
OPENFILE_BUTTON,
CLOSETAB_BUTTON,
CLOSEWINDOW_BUTTON,
SAVEPAGE_BUTTON,
PDF_BUTTON,
PLAINTEXT_BUTTON,
DRAWFILE_BUTTON,
POSTSCRIPT_BUTTON,
PRINTPREVIEW_BUTTON,
PRINT_BUTTON,
QUIT_BUTTON,
CUT_BUTTON,
COPY_BUTTON,
PASTE_BUTTON,
DELETE_BUTTON,
SELECTALL_BUTTON,
FIND_BUTTON,
PREFERENCES_BUTTON,
ZOOMPLUS_BUTTON,
ZOOMMINUS_BUTTON,
ZOOMNORMAL_BUTTON,
FULLSCREEN_BUTTON,
VIEWSOURCE_BUTTON,
DOWNLOADS_BUTTON,
SAVEWINDOWSIZE_BUTTON,
TOGGLEDEBUGGING_BUTTON,
SAVEBOXTREE_BUTTON,
SAVEDOMTREE_BUTTON,
LOCALHISTORY_BUTTON,
GLOBALHISTORY_BUTTON,
ADDBOOKMARKS_BUTTON,
SHOWBOOKMARKS_BUTTON,
OPENLOCATION_BUTTON,
NEXTTAB_BUTTON,
PREVTAB_BUTTON,
CONTENTS_BUTTON,
GUIDE_BUTTON,
INFO_BUTTON,
ABOUT_BUTTON,
PLACEHOLDER_BUTTON /* size indicator; array maximum indices */
} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */
struct gtk_history_window {
struct gtk_scaffolding *g;
GtkWindow *window;
GtkNotebook *notebook;
GtkEntry *url_bar;
GtkEntryCompletion *url_bar_completion;
GtkStatusbar *status_bar;
GtkMenuItem *edit_menu;
GtkMenuItem *tabs_menu;
GtkToolbar *tool_bar;
GtkToolButton *back_button;
GtkToolButton *history_button;
GtkToolButton *forward_button;
GtkToolButton *stop_button;
GtkToolButton *reload_button;
GtkMenuBar *menu_bar;
GtkMenuItem *back_menu;
GtkMenuItem *forward_menu;
GtkMenuItem *stop_menu;
GtkMenuItem *reload_menu;
GtkImage *throbber;
GtkPaned *status_pane;
GladeXML *xml;
GladeXML *popup_xml;
GtkMenu *popup_menu;
struct gtk_history_window *history_window;
GtkDialog *preferences_dialog;
int throb_frame;
struct gui_window *top_level;
int being_destroyed;
bool fullscreen;
GtkScrolledWindow *scrolled;
GtkDrawingArea *drawing_area;
};
GtkWindow *nsgtk_get_window_for_scaffold(struct gtk_scaffolding *g);
struct gtk_search {
GtkToolbar *bar;
GtkEntry *entry;
GtkToolButton *buttons[3]; /* back, forward, */
GtkCheckButton *checkAll; /* close */
GtkCheckButton *caseSens;
};
struct nsgtk_button_connect {
GtkToolItem *button;
int location; /* in toolbar */
bool sensitivity;
GtkImageMenuItem *main;
GtkImageMenuItem *rclick;
GtkImageMenuItem *popup;
void *mhandler; /* menu item clicked */
void *bhandler; /* button clicked */
void *dataplus; /* customization -> toolbar */
void *dataminus; /* customization -> store */
};
extern nsgtk_scaffolding *scaf_list;
nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel);
gboolean nsgtk_scaffolding_is_busy(nsgtk_scaffolding *scaffold);
bool nsgtk_scaffolding_is_busy(nsgtk_scaffolding *g);
GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g);
GtkWindow *nsgtk_scaffolding_window(nsgtk_scaffolding *g);
GtkNotebook *nsgtk_scaffolding_notebook(nsgtk_scaffolding *g);
GtkWidget *nsgtk_scaffolding_urlbar(nsgtk_scaffolding *g);
GtkWidget *nsgtk_scaffolding_websearch(nsgtk_scaffolding *g);
GtkToolbar *nsgtk_scaffolding_toolbar(nsgtk_scaffolding *g);
struct nsgtk_button_connect *nsgtk_scaffolding_button(nsgtk_scaffolding *g,
int i);
struct gtk_search *nsgtk_scaffolding_search(nsgtk_scaffolding *g);
GtkMenuBar *nsgtk_scaffolding_menu_bar(nsgtk_scaffolding *g);
struct gtk_history_window *nsgtk_scaffolding_history_window(nsgtk_scaffolding
*g);
struct gui_window *nsgtk_scaffolding_top_level(nsgtk_scaffolding *g);
void nsgtk_scaffolding_reset_offset(nsgtk_scaffolding *g);
nsgtk_scaffolding *nsgtk_scaffolding_iterate(nsgtk_scaffolding *g);
void nsgtk_scaffolding_toolbar_init(struct gtk_scaffolding *g);
void nsgtk_scaffolding_update_url_bar_ref(nsgtk_scaffolding *g);
void nsgtk_scaffolding_update_throbber_ref(nsgtk_scaffolding *g);
void nsgtk_scaffolding_update_websearch_ref(nsgtk_scaffolding *g);
void nsgtk_scaffolding_set_websearch(nsgtk_scaffolding *g, const char
*content);
void nsgtk_scaffolding_toggle_search_bar_visibility(nsgtk_scaffolding *g);
void nsgtk_scaffolding_set_top_level(struct gui_window *g);
GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g);
void nsgtk_scaffolding_set_top_level (struct gui_window *gw);
void nsgtk_scaffolding_destroy(nsgtk_scaffolding *scaffold);
void nsgtk_scaffolding_destroy(nsgtk_scaffolding *g);
void nsgtk_scaffolding_set_sensitivity(struct gtk_scaffolding *g);
void nsgtk_scaffolding_initial_sensitivity(struct gtk_scaffolding *g);
void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x,
gdouble y);
void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget,
GtkAllocation *alloc, gpointer data);
gboolean nsgtk_window_url_activate_event(GtkWidget *, gpointer);
gboolean nsgtk_window_url_changed(GtkWidget *, GdkEventKey *, gpointer);
#define MULTIPROTO(q)\
gboolean nsgtk_on_##q##_activate(struct gtk_scaffolding *);\
gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *, gpointer);\
gboolean nsgtk_on_##q##_activate_button(GtkButton *, gpointer)
#define MENUPROTO(q)\
gboolean nsgtk_on_##q##_activate(GtkMenuItem *, gpointer)
#define BUTTONPROTO(q)\
gboolean nsgtk_on_##q##_activate(GtkButton *, gpointer)
/* prototypes for handlers */
/* file menu */
MULTIPROTO(newwindow);
MULTIPROTO(newtab);
MULTIPROTO(open_location);
MULTIPROTO(openfile);
MULTIPROTO(savepage);
MULTIPROTO(pdf);
MULTIPROTO(plaintext);
MULTIPROTO(drawfile);
MULTIPROTO(postscript);
MULTIPROTO(printpreview);
MULTIPROTO(print);
MULTIPROTO(closewindow);
MULTIPROTO(quit);
/* edit menu */
MULTIPROTO(cut);
MULTIPROTO(copy);
MULTIPROTO(paste);
MULTIPROTO(delete);
MULTIPROTO(selectall);
MULTIPROTO(find);
MULTIPROTO(preferences);
/* view menu */
MULTIPROTO(stop);
MULTIPROTO(reload);
MULTIPROTO(zoomplus);
MULTIPROTO(zoomnormal);
MULTIPROTO(zoomminus);
MULTIPROTO(fullscreen);
MULTIPROTO(viewsource);
MENUPROTO(menubar);
MENUPROTO(toolbar);
MENUPROTO(statusbar);
MULTIPROTO(downloads);
MULTIPROTO(savewindowsize);
MULTIPROTO(toggledebugging);
MULTIPROTO(saveboxtree);
MULTIPROTO(savedomtree);
/* navigate menu */
MULTIPROTO(back);
MULTIPROTO(forward);
MULTIPROTO(home);
MULTIPROTO(localhistory);
MULTIPROTO(globalhistory);
MULTIPROTO(addbookmarks);
MULTIPROTO(showbookmarks);
MULTIPROTO(openlocation);
/* tabs menu */
MULTIPROTO(nexttab);
MULTIPROTO(prevtab);
MULTIPROTO(closetab);
/* help menu */
MULTIPROTO(contents);
MULTIPROTO(guide);
MULTIPROTO(info);
MULTIPROTO(about);
/* popup menu */
MENUPROTO(customize);
MENUPROTO(savelink);
MENUPROTO(linkfocused);
MENUPROTO(linkbackground);
/* non-menu */
BUTTONPROTO(history);
#undef MULTIPROTO
#undef MENUPROTO
#undef BUTTONPROTO
#endif /* NETSURF_GTK_SCAFFOLDING_H */

263
gtk/gtk_search.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Free text search (front component)
*/
#include <ctype.h>
#include <string.h>
#include <gdk/gdkkeysyms.h>
#include "gtk/gtk_search.h"
#include "gtk/gtk_scaffolding.h"
#include "gtk/gtk_window.h"
#include "utils/config.h"
#include "content/content.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/search.h"
#include "desktop/searchweb.h"
#include "desktop/selection.h"
#include "render/box.h"
#include "render/html.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
static void nsgtk_search_init(struct gtk_scaffolding *g);
static void nsgtk_search_set_status(bool found, void *p);
static void nsgtk_search_set_hourglass(bool active, void *p);
static void nsgtk_search_add_recent(const char *string, void *p);
static struct search_callbacks nsgtk_search_callbacks = {
nsgtk_search_set_forward_state,
nsgtk_search_set_back_state,
nsgtk_search_set_status,
nsgtk_search_set_hourglass,
nsgtk_search_add_recent
};
/** connected to the search forward button */
gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data)
{
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
struct browser_window *bw = gui_window_get_browser_window(
nsgtk_scaffolding_top_level(g));
nsgtk_search_init(g);
search_flags_t flags = SEARCH_FLAG_FORWARDS |
(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->caseSens)) ?
SEARCH_FLAG_CASE_SENSITIVE : 0) |
(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->checkAll)) ?
SEARCH_FLAG_SHOWALL : 0);
if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw))
search_step(bw->search_context, flags, gtk_entry_get_text(
nsgtk_scaffolding_search(g)->entry));
return TRUE;
}
/** connected to the search back button */
gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
{
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
struct browser_window *bw = gui_window_get_browser_window(
nsgtk_scaffolding_top_level(g));
nsgtk_search_init(g);
search_flags_t flags = 0 |(gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->caseSens)) ?
SEARCH_FLAG_CASE_SENSITIVE : 0) |
(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->checkAll)) ?
SEARCH_FLAG_SHOWALL : 0);
if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw))
search_step(bw->search_context, flags, gtk_entry_get_text(
nsgtk_scaffolding_search(g)->entry));
return TRUE;
}
/** preparatory code when the search bar is made visible initially */
void nsgtk_search_init(struct gtk_scaffolding *g)
{
struct content *c;
assert(gui_window_get_browser_window(nsgtk_scaffolding_top_level(g))
!= NULL);
c = gui_window_get_browser_window(nsgtk_scaffolding_top_level(g))->
current_content;
if ((!c) || (c->type != CONTENT_HTML && c->type != CONTENT_TEXTPLAIN))
return;
}
/** connected to the search close button */
gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data)
{
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
nsgtk_scaffolding_toggle_search_bar_visibility(g);
return TRUE;
}
/** connected to the search entry [typing] */
gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data)
{
nsgtk_scaffolding *g = (nsgtk_scaffolding *)data;
struct browser_window *bw = gui_window_get_browser_window(
nsgtk_scaffolding_top_level(g));
if ((bw != NULL) && (bw->search_context != NULL))
search_destroy_context(bw->search_context);
nsgtk_search_set_forward_state(true, (void *)bw);
nsgtk_search_set_back_state(true, (void *)bw);
return TRUE;
}
/** connected to the search entry [return key] */
gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data)
{
nsgtk_scaffolding *g = (nsgtk_scaffolding *)data;
struct browser_window *bw = gui_window_get_browser_window(
nsgtk_scaffolding_top_level(g));
nsgtk_search_init(g);
search_flags_t flags = SEARCH_FLAG_FORWARDS |
(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->caseSens)) ?
SEARCH_FLAG_CASE_SENSITIVE : 0) |
(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
nsgtk_scaffolding_search(g)->checkAll)) ?
SEARCH_FLAG_SHOWALL : 0);
if (search_verify_new(bw, &nsgtk_search_callbacks, (void *)bw))
search_step(bw->search_context, flags, gtk_entry_get_text(
nsgtk_scaffolding_search(g)->entry));
return FALSE;
}
/** allows escape key to close search bar too */
gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_Escape) {
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
nsgtk_scaffolding_toggle_search_bar_visibility(g);
}
return FALSE;
}
/** connected to the websearch entry [return key] */
gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data)
{
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
temp_open_background = 0;
search_web_new_window(gui_window_get_browser_window(
nsgtk_scaffolding_top_level(g)),
(char *)gtk_entry_get_text(GTK_ENTRY(
nsgtk_scaffolding_websearch(g))));
temp_open_background = -1;
return TRUE;
}
/**
* allows a click in the websearch entry field to clear the name of the
* provider
*/
gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f,
gpointer data)
{
struct gtk_scaffolding *g = (struct gtk_scaffolding *)data;
gtk_editable_select_region(GTK_EDITABLE(
nsgtk_scaffolding_websearch(g)), 0, -1);
gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_websearch(g)));
return TRUE;
}
/**
* Change the displayed search status.
* \param found search pattern matched in text
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void nsgtk_search_set_status(bool found, void *p)
{
}
/**
* display hourglass while searching
* \param active start/stop indicator
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void nsgtk_search_set_hourglass(bool active, void *p)
{
}
/**
* add search string to recent searches list
* front is at liberty how to implement the bare notification
* should normally store a strdup() of the string;
* core gives no guarantee of the integrity of the const char *
* \param string search pattern
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void nsgtk_search_add_recent(const char *string, void *p)
{
}
/**
* activate search forwards button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void nsgtk_search_set_forward_state(bool active, void *p)
{
struct browser_window *bw = (struct browser_window *)p;
if ((bw != NULL) && (bw->window != NULL)) {
struct gtk_scaffolding *g = nsgtk_get_scaffold(bw->window);
gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search(
g)->buttons[1]), active);
}
}
/**
* activate search back button in gui
* \param active activate/inactivate
* \param p the pointer sent to search_verify_new() / search_create_context()
*/
void nsgtk_search_set_back_state(bool active, void *p)
{
struct browser_window *bw = (struct browser_window *)p;
if ((bw != NULL) && (bw->window != NULL)) {
struct gtk_scaffolding *g = nsgtk_get_scaffold(bw->window);
gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search(
g)->buttons[0]), active);
}
}

39
gtk/gtk_search.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_GTK_SEARCH_H_
#define _NETSURF_GTK_SEARCH_H_
#include <gtk/gtk.h>
#include "gtk/gtk_scaffolding.h"
void nsgtk_search_bar_toggle_visibility(struct gtk_scaffolding * g);
gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data);
gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data);
gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event,
gpointer data);
gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data);
gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data);
gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data);
gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data);
gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f,
gpointer data);
void nsgtk_search_set_forward_state(bool active, void *p);
void nsgtk_search_set_back_state(bool active, void *p);
#endif

View File

@ -79,7 +79,7 @@ void gui_start_selection(struct gui_window *g)
else
g_string_set_size(current_selection, 0);
gtk_widget_grab_focus(GTK_WIDGET(g->drawing_area));
gtk_widget_grab_focus(GTK_WIDGET(nsgtk_window_get_drawing_area(g)));
}
void gui_paste_from_clipboard(struct gui_window *g, int x, int y)
@ -89,7 +89,8 @@ void gui_paste_from_clipboard(struct gui_window *g, int x, int y)
text = gtk_clipboard_wait_for_text (clipboard);
/* clipboard_wait... converts the string to utf8 for us */
if (text != NULL)
browser_window_paste_text(g->bw, text, strlen(text), true);
browser_window_paste_text(gui_window_get_browser_window(g),
text, strlen(text), true);
g_free(text);
}

View File

@ -23,12 +23,14 @@
#include "desktop/browser.h"
#include "content/content.h"
#include "desktop/options.h"
#include "desktop/search.h"
#include "utils/utils.h"
#include "gtk/options.h"
#include "gtk/gtk_search.h"
#include "gtk/gtk_tabs.h"
#define TAB_WIDTH_N_CHARS 15
#define GET_WIDGET(x) glade_xml_get_widget(gladeWindows, (x))
#define GET_WIDGET(x) glade_xml_get_widget(gladeNetsurf, (x))
static GtkWidget *nsgtk_tab_label_setup(struct gui_window *window);
static void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child,
@ -58,15 +60,19 @@ void nsgtk_tab_init(GtkWidget *tabs)
void nsgtk_tab_add(struct gui_window *window, bool background)
{
GtkWidget *tabs = GTK_WIDGET(nsgtk_scaffolding_get_notebook(window));
GtkWidget *tabs = GTK_WIDGET(nsgtk_scaffolding_notebook(
nsgtk_get_scaffold(window)));
GtkWidget *tabBox = nsgtk_tab_label_setup(window);
gint remember = gtk_notebook_get_current_page(GTK_NOTEBOOK(tabs));
gtk_notebook_append_page(GTK_NOTEBOOK(tabs),
GTK_WIDGET(window->scrolledwindow), tabBox);
/*causes gtk errors can't set a parent
GTK_WIDGET(nsgtk_window_get_scrolledwindow(window)),
tabBox);
/*causes gtk errors can't set a parent */
gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(tabs),
GTK_WIDGET(window->scrolledwindow), true); */
gtk_widget_show_all(GTK_WIDGET(window->scrolledwindow));
GTK_WIDGET(nsgtk_window_get_scrolledwindow(window)),
true);
gtk_widget_show_all(GTK_WIDGET(nsgtk_window_get_scrolledwindow(
window)));
gtk_notebook_set_current_page(GTK_NOTEBOOK(tabs),
gtk_notebook_get_n_pages(GTK_NOTEBOOK(tabs)) - 1);
if (option_new_blank) {
@ -75,13 +81,15 @@ void nsgtk_tab_add(struct gui_window *window, bool background)
blankpage = g_strconcat("file:///", res_dir_location,
"blankpage", NULL); */
/* segfaults
struct browser_window *bw = nsgtk_get_browser_for_gui(window);
struct browser_window *bw =
gui_window_get_browser_window(window);
browser_window_go(bw, blankpage, 0, true); */
/* free(blankpage); */
}
if (background)
gtk_notebook_set_current_page(GTK_NOTEBOOK(tabs), remember);
gtk_widget_grab_focus(GTK_WIDGET(window->scaffold->url_bar));
gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_urlbar(
nsgtk_get_scaffold(window))));
}
void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child,
@ -97,12 +105,14 @@ void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child,
void nsgtk_tab_set_title(struct gui_window *g, const char *title)
{
GtkWidget *label;
gboolean is_top_level = (g->tab != NULL);
GtkWidget *tab;
tab = nsgtk_window_get_tab(g);
gboolean is_top_level = (tab != NULL);
if (is_top_level) {
label = g_object_get_data(G_OBJECT(g->tab), "label");
label = g_object_get_data(G_OBJECT(tab), "label");
gtk_label_set_text(GTK_LABEL(label), title);
gtk_widget_set_tooltip_text(g->tab, title);
gtk_widget_set_tooltip_text(tab, title);
}
}
@ -147,7 +157,7 @@ GtkWidget *nsgtk_tab_label_setup(struct gui_window *window)
g_object_set_data(G_OBJECT(hbox), "label", label);
g_object_set_data(G_OBJECT(hbox), "close-button", button);
window->tab = hbox;
nsgtk_window_set_tab(window, hbox);
gtk_widget_show_all(hbox);
return hbox;
@ -183,6 +193,11 @@ void nsgtk_tab_page_changed(GtkNotebook *notebook, GtkNotebookPage *page,
GtkWidget *window = gtk_notebook_get_nth_page(notebook, page_num);
struct gui_window *gw = g_object_get_data(G_OBJECT(window),
"gui_window");
struct browser_window *bw = gui_window_get_browser_window(gw);
if ((bw != NULL) && (bw->search_context != NULL))
search_destroy_context(bw->search_context);
nsgtk_search_set_forward_state(true, bw);
nsgtk_search_set_back_state(true, bw);
if (gw)
nsgtk_scaffolding_set_top_level(gw);
}

773
gtk/gtk_theme.c Normal file
View File

@ -0,0 +1,773 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#include <stdio.h>
#include <sys/stat.h>
#include "content/content.h"
#include "content/content_type.h"
#include "gtk/gtk_gui.h"
#include "gtk/gtk_scaffolding.h"
#include "gtk/gtk_menu.h"
#include "gtk/gtk_theme.h"
#include "gtk/gtk_window.h"
#include "gtk/options.h"
#include "gtk/dialogs/gtk_options.h"
#include "utils/container.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
enum image_sets {
IMAGE_SET_MAIN_MENU = 0,
IMAGE_SET_RCLICK_MENU,
IMAGE_SET_POPUP_MENU,
IMAGE_SET_BUTTONS,
IMAGE_SET_COUNT
};
struct nsgtk_theme_cache {
GdkPixbuf *image[PLACEHOLDER_BUTTON];
GdkPixbuf *searchimage[SEARCH_BUTTONS_COUNT];
/* apng throbber image */
};
static char *current_theme_name = NULL;
static struct nsgtk_theme_cache *theme_cache_menu = NULL;
static struct nsgtk_theme_cache *theme_cache_toolbar = NULL;
static struct nsgtk_theme *nsgtk_theme_default(GtkIconSize s);
static GtkImage *nsgtk_theme_image_default(nsgtk_toolbar_button i,
GtkIconSize s);
static bool nsgtk_theme_verify(const char *themename);
static void nsgtk_theme_cache_image(nsgtk_toolbar_button i,
const char *filename, const char *path);
static void nsgtk_theme_cache_searchimage(nsgtk_search_buttons i,
const char *filename, const char *path);
#ifdef WITH_THEME_INSTALL
static struct content *theme_install_content = NULL;
static void theme_install_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
static bool theme_install_read(const char *data, unsigned long len);
#endif
/**
* called during gui init phase to retrieve theme name from file then
* implement
*/
void nsgtk_theme_init(void)
{
size_t len;
if (option_current_theme == 0)
return;
len = SLEN("themelist") + strlen(res_dir_location) + 1;
char themefile[len];
snprintf(themefile, len, "%s%s", res_dir_location, "themelist");
nsgtk_scaffolding *list = scaf_list;
nsgtk_theme_verify(NULL);
FILE *fp = fopen(themefile, "r");
if (fp == NULL)
return;
char buf[50];
int row_count = 0;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (buf[0] == '\0')
continue;
if (row_count++ == option_current_theme) {
if (current_theme_name != NULL)
free(current_theme_name);
/* clear the '\n' ["\n\0"->"\0\0"] */
buf[strlen(buf) - 1] = '\0';
current_theme_name = strdup(buf);
break;
}
}
fclose(fp);
while (list != NULL) {
nsgtk_theme_implement(list);
list = nsgtk_scaffolding_iterate(list);
}
}
/**
* return reference to static global current_theme_name; caller then has
* responsibility for global reference
*/
char *nsgtk_theme_name(void)
{
return current_theme_name;
}
/**
* set static global current_theme_name from param; caller is responsible
* for the integrity of the global reference
*/
void nsgtk_theme_set_name(char *name)
{
current_theme_name = name;
}
/**
* adds a theme name to the list of themes
*/
void nsgtk_theme_add(const char *themename)
{
size_t len;
GtkWidget *notification, *label;
len = SLEN("themelist") + strlen(res_dir_location) + 1;
char themefile[len];
snprintf(themefile, len, "%s%s", res_dir_location, "themelist");
/* conduct verification here; no adding duplicates to list */
if (nsgtk_theme_verify(themename) == false) {
warn_user(messages_get("gtkThemeDup"), 0);
return;
}
FILE *fp = fopen(themefile, "a");
if (fp == NULL) {
warn_user(messages_get("gtkFileError"), themefile);
return;
}
fprintf(fp, "%s\n", themename);
fclose(fp);
/* notification that theme was added successfully */
notification = gtk_dialog_new_with_buttons(messages_get("gtkThemeAdd"),
NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK,
GTK_RESPONSE_NONE, NULL);
if (notification == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
len = SLEN("\t\t\t\t\t\t") + strlen(messages_get("gtkThemeAdd")) + 1;
char labelcontent[len];
snprintf(labelcontent, len, "\t\t\t%s\t\t\t",
messages_get("gtkThemeAdd"));
label = gtk_label_new(labelcontent);
if (label == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
g_signal_connect_swapped(notification, "response",
G_CALLBACK(gtk_widget_destroy), notification);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(notification)->vbox), label);
gtk_widget_show_all(notification);
/* update combo */
if (wndPreferences == NULL)
return;
nsgtk_options_combo_theme_add(themename);
}
/**
* \param themename contains a name of theme to check whether it may
* properly be added to the list; alternatively NULL to check the integrity
* of the list
* \return true for themename may be added / every item in the list is
* a valid directory
*/
bool nsgtk_theme_verify(const char *themename)
{
long filelength;
FILE *fp;
size_t val = SLEN("themelist") + strlen(res_dir_location) + 1;
char buf[50];
char themefile[val];
snprintf(themefile, val, "%s%s", res_dir_location, "themelist");
if (themename == NULL) {
char *filecontent, *testfile;
struct stat sta;
fp = fopen(themefile, "r+");
if (fp == NULL) {
warn_user(messages_get("gtkFileError"), themefile);
return true;
}
fseek(fp, 0L, SEEK_END);
filelength = ftell(fp);
filecontent = malloc(filelength +
SLEN("gtk default theme\n") + SLEN("\n")
+ 1);
if (filecontent == NULL) {
warn_user(messages_get("NoMemory"), 0);
return true;
}
strcpy(filecontent, "gtk default theme\n");
fseek(fp, 0L, SEEK_SET);
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* iterate list */
buf[strlen(buf) - 1] = '\0';
/* "\n\0" -> "\0\0" */
testfile = malloc(strlen(res_dir_location) +
SLEN("themes/") + strlen(buf) + 1);
if (testfile == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(filecontent);
return false;
}
sprintf(testfile, "%sthemes/%s", res_dir_location,
buf);
/* check every directory */
if (access(testfile, R_OK) == 0) {
stat(testfile, &sta);
if (S_ISDIR(sta.st_mode)) {
buf[strlen(buf)] = '\n';
/* "\0\0" -> "\n\0" */
strcat(filecontent, buf);
}
}
free(testfile);
}
fclose(fp);
fp = fopen(themefile, "w");
if (fp == NULL) {
warn_user(messages_get("gtkFileError"), themefile);
free(filecontent);
return true;
}
val = fwrite(filecontent, strlen(filecontent), 1, fp);
if (val == 0)
LOG(("empty write themelist"));
fclose(fp);
free(filecontent);
return true;
} else {
fp = fopen(themefile, "r");
if (fp == NULL) {
warn_user(messages_get("gtkFileError"), themefile);
return false;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
buf[strlen(buf) - 1] = '\0';
/* "\n\0" -> "\0\0" */
if (strcmp(buf, themename) == 0) {
fclose(fp);
return false;
}
}
fclose(fp);
return true;
}
}
/**
* sets the images for a particular scaffolding according to the current theme
*/
void nsgtk_theme_implement(struct gtk_scaffolding *g)
{
struct nsgtk_theme *theme[IMAGE_SET_COUNT];
int i;
struct nsgtk_button_connect *button;
struct gtk_search *search;
for (i = 0; i <= IMAGE_SET_POPUP_MENU; i++)
theme[i] = nsgtk_theme_load(GTK_ICON_SIZE_MENU);
theme[IMAGE_SET_BUTTONS] =
nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR);
for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
if ((i == URL_BAR_ITEM) || (i == THROBBER_ITEM) ||
(i == WEBSEARCH_ITEM))
continue;
button = nsgtk_scaffolding_button(g, i);
if (button == NULL)
continue;
/* gtk_image_menu_item_set_image accepts NULL image */
if ((button->main != NULL) &&
(theme[IMAGE_SET_MAIN_MENU] != NULL)) {
gtk_image_menu_item_set_image(button->main,
GTK_WIDGET(
theme[IMAGE_SET_MAIN_MENU]->
image[i]));
gtk_widget_show_all(GTK_WIDGET(button->main));
}
if ((button->rclick != NULL) &&
(theme[IMAGE_SET_RCLICK_MENU] != NULL)) {
gtk_image_menu_item_set_image(button->rclick,
GTK_WIDGET(
theme[IMAGE_SET_RCLICK_MENU]->
image[i]));
gtk_widget_show_all(GTK_WIDGET(button->rclick));
}
if ((button->popup != NULL) &&
(theme[IMAGE_SET_POPUP_MENU] != NULL)) {
gtk_image_menu_item_set_image(button->popup,
GTK_WIDGET(
theme[IMAGE_SET_POPUP_MENU]->
image[i]));
gtk_widget_show_all(GTK_WIDGET(button->popup));
}
if ((button->location != -1) && (button->button != NULL) &&
(theme[IMAGE_SET_BUTTONS] != NULL)) {
gtk_tool_button_set_icon_widget(
GTK_TOOL_BUTTON(button->button),
GTK_WIDGET(
theme[IMAGE_SET_BUTTONS]->
image[i]));
gtk_widget_show_all(GTK_WIDGET(button->button));
}
}
/* set search bar images */
search = nsgtk_scaffolding_search(g);
if ((search != NULL) && (theme[IMAGE_SET_MAIN_MENU] != NULL)) {
/* gtk_tool_button_set_icon_widget accepts NULL image */
if (search->buttons[SEARCH_BACK_BUTTON] != NULL) {
gtk_tool_button_set_icon_widget(
search->buttons[SEARCH_BACK_BUTTON],
GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
searchimage[SEARCH_BACK_BUTTON]));
gtk_widget_show_all(GTK_WIDGET(
search->buttons[SEARCH_BACK_BUTTON]));
}
if (search->buttons[SEARCH_FORWARD_BUTTON] != NULL) {
gtk_tool_button_set_icon_widget(
search->buttons[SEARCH_FORWARD_BUTTON],
GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
searchimage[SEARCH_FORWARD_BUTTON]));
gtk_widget_show_all(GTK_WIDGET(
search->buttons[
SEARCH_FORWARD_BUTTON]));
}
if (search->buttons[SEARCH_CLOSE_BUTTON] != NULL) {
gtk_tool_button_set_icon_widget(
search->buttons[SEARCH_CLOSE_BUTTON],
GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
searchimage[SEARCH_CLOSE_BUTTON]));
gtk_widget_show_all(GTK_WIDGET(
search->buttons[SEARCH_CLOSE_BUTTON]));
}
}
for (i = 0; i < IMAGE_SET_COUNT; i++)
if (theme[i] != NULL)
free(theme[i]);
}
/**
* creates a set of images to add to buttons / menus
* loads images from cache, calling an update to the cache when necessary
* \return a struct nsgtk_theme is an array of images
*/
struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s)
{
if (current_theme_name == NULL)
return nsgtk_theme_default(s);
struct nsgtk_theme *theme = malloc(sizeof(struct nsgtk_theme));
if (theme == NULL)
return theme;
if ((theme_cache_menu == NULL) || (theme_cache_toolbar == NULL))
nsgtk_theme_prepare();
/* load theme from cache */
struct nsgtk_theme_cache *cachetheme = (s == GTK_ICON_SIZE_MENU) ?
theme_cache_menu : theme_cache_toolbar;
if (cachetheme == NULL)
return NULL;
#define SET_BUTTON_IMAGE(p, q, r)\
if (p->image[q##_BUTTON] != NULL)\
r->image[q##_BUTTON] = GTK_IMAGE(gtk_image_new_from_pixbuf(\
p->image[q##_BUTTON]));\
else\
r->image[q##_BUTTON] = nsgtk_theme_image_default(\
q##_BUTTON, s);
SET_BUTTON_IMAGE(cachetheme, BACK, theme)
SET_BUTTON_IMAGE(cachetheme, HISTORY, theme)
SET_BUTTON_IMAGE(cachetheme, FORWARD, theme)
SET_BUTTON_IMAGE(cachetheme, STOP, theme)
SET_BUTTON_IMAGE(cachetheme, RELOAD, theme)
SET_BUTTON_IMAGE(cachetheme, HOME, theme)
SET_BUTTON_IMAGE(cachetheme, NEWWINDOW, theme)
SET_BUTTON_IMAGE(cachetheme, NEWTAB, theme)
SET_BUTTON_IMAGE(cachetheme, OPENFILE, theme)
SET_BUTTON_IMAGE(cachetheme, CLOSETAB, theme)
SET_BUTTON_IMAGE(cachetheme, CLOSEWINDOW, theme)
SET_BUTTON_IMAGE(cachetheme, SAVEPAGE, theme)
SET_BUTTON_IMAGE(cachetheme, PRINTPREVIEW, theme)
SET_BUTTON_IMAGE(cachetheme, PRINT, theme)
SET_BUTTON_IMAGE(cachetheme, QUIT, theme)
SET_BUTTON_IMAGE(cachetheme, CUT, theme)
SET_BUTTON_IMAGE(cachetheme, COPY, theme)
SET_BUTTON_IMAGE(cachetheme, PASTE, theme)
SET_BUTTON_IMAGE(cachetheme, DELETE, theme)
SET_BUTTON_IMAGE(cachetheme, SELECTALL, theme)
SET_BUTTON_IMAGE(cachetheme, PREFERENCES, theme)
SET_BUTTON_IMAGE(cachetheme, ZOOMPLUS, theme)
SET_BUTTON_IMAGE(cachetheme, ZOOMMINUS, theme)
SET_BUTTON_IMAGE(cachetheme, ZOOMNORMAL, theme)
SET_BUTTON_IMAGE(cachetheme, FULLSCREEN, theme)
SET_BUTTON_IMAGE(cachetheme, VIEWSOURCE, theme)
SET_BUTTON_IMAGE(cachetheme, CONTENTS, theme)
SET_BUTTON_IMAGE(cachetheme, ABOUT, theme)
SET_BUTTON_IMAGE(cachetheme, PDF, theme)
SET_BUTTON_IMAGE(cachetheme, PLAINTEXT, theme)
SET_BUTTON_IMAGE(cachetheme, DRAWFILE, theme)
SET_BUTTON_IMAGE(cachetheme, POSTSCRIPT, theme)
SET_BUTTON_IMAGE(cachetheme, FIND, theme)
SET_BUTTON_IMAGE(cachetheme, DOWNLOADS, theme)
SET_BUTTON_IMAGE(cachetheme, SAVEWINDOWSIZE, theme)
SET_BUTTON_IMAGE(cachetheme, TOGGLEDEBUGGING, theme)
SET_BUTTON_IMAGE(cachetheme, SAVEBOXTREE, theme)
SET_BUTTON_IMAGE(cachetheme, SAVEDOMTREE, theme)
SET_BUTTON_IMAGE(cachetheme, LOCALHISTORY, theme)
SET_BUTTON_IMAGE(cachetheme, GLOBALHISTORY, theme)
SET_BUTTON_IMAGE(cachetheme, ADDBOOKMARKS, theme)
SET_BUTTON_IMAGE(cachetheme, SHOWBOOKMARKS, theme)
SET_BUTTON_IMAGE(cachetheme, OPENLOCATION, theme)
SET_BUTTON_IMAGE(cachetheme, NEXTTAB, theme)
SET_BUTTON_IMAGE(cachetheme, PREVTAB, theme)
SET_BUTTON_IMAGE(cachetheme, GUIDE, theme)
SET_BUTTON_IMAGE(cachetheme, INFO, theme)
#undef SET_BUTTON_IMAGE
#define SET_BUTTON_IMAGE(p, q, qq, r)\
if (qq->searchimage[SEARCH_##p##_BUTTON] != NULL)\
r->searchimage[SEARCH_##p##_BUTTON] =\
GTK_IMAGE(gtk_image_new_from_pixbuf(\
qq->searchimage[\
SEARCH_##p##_BUTTON]));\
else if (qq->image[q##_BUTTON] != NULL)\
r->searchimage[SEARCH_##p##_BUTTON] =\
GTK_IMAGE(gtk_image_new_from_pixbuf(\
qq->image[q##_BUTTON]));\
else\
r->searchimage[SEARCH_##p##_BUTTON] =\
nsgtk_theme_image_default(\
PLACEHOLDER_BUTTON + SEARCH_##p##_BUTTON, s);
SET_BUTTON_IMAGE(BACK, BACK, cachetheme, theme)
SET_BUTTON_IMAGE(FORWARD, FORWARD, cachetheme, theme)
SET_BUTTON_IMAGE(CLOSE, CLOSEWINDOW, cachetheme, theme)
#undef SET_BUTTON_IMAGE
return theme;
}
/**
* caches individual theme images from file
* \param i the toolbar button reference
* \param filename the image file name
* \param path the path to the theme folder
*/
void nsgtk_theme_cache_image(nsgtk_toolbar_button i, const char *filename,
const char *path)
{
char fullpath[strlen(filename) + strlen(path) + 1];
sprintf(fullpath, "%s%s", path, filename);
if (theme_cache_toolbar != NULL)
theme_cache_toolbar->image[i] =
gdk_pixbuf_new_from_file_at_size(fullpath,
24, 24, NULL);
if (theme_cache_menu != NULL)
theme_cache_menu->image[i] = gdk_pixbuf_new_from_file_at_size(
fullpath, 16, 16, NULL);
}
void nsgtk_theme_cache_searchimage(nsgtk_search_buttons i,
const char *filename, const char *path)
{
char fullpath[strlen(filename) + strlen(path) + 1];
sprintf(fullpath, "%s%s", path, filename);
if (theme_cache_toolbar != NULL)
theme_cache_toolbar->searchimage[i] =
gdk_pixbuf_new_from_file_at_size(fullpath,
24, 24, NULL);
if (theme_cache_menu != NULL)
theme_cache_menu->searchimage[i] =
gdk_pixbuf_new_from_file_at_size(fullpath,
16, 16, NULL);
}
/**
* caches theme images from file as pixbufs
*/
void nsgtk_theme_prepare(void)
{
if (current_theme_name == NULL)
return;
if (theme_cache_menu == NULL)
theme_cache_menu = malloc(sizeof(struct nsgtk_theme_cache));
if (theme_cache_toolbar == NULL)
theme_cache_toolbar = malloc(sizeof(struct nsgtk_theme_cache));
size_t len = strlen(res_dir_location) + SLEN("/themes/") +
strlen(current_theme_name) + 1;
char path[len];
snprintf(path, len, "%sthemes/%s/", res_dir_location,
current_theme_name);
#define CACHE_IMAGE(p, q, r)\
nsgtk_theme_cache_image(p##_BUTTON, #q ".png", r)
CACHE_IMAGE(BACK, back, path);
CACHE_IMAGE(HISTORY, history, path);
CACHE_IMAGE(FORWARD, forward, path);
CACHE_IMAGE(STOP, stop, path);
CACHE_IMAGE(RELOAD, reload, path);
CACHE_IMAGE(HOME, home, path);
CACHE_IMAGE(NEWWINDOW, newwindow, path);
CACHE_IMAGE(NEWTAB, newtab, path);
CACHE_IMAGE(OPENFILE, openfile, path);
CACHE_IMAGE(CLOSETAB, closetab, path);
CACHE_IMAGE(CLOSEWINDOW, closewindow, path);
CACHE_IMAGE(SAVEPAGE, savepage, path);
CACHE_IMAGE(PRINTPREVIEW, printpreview, path);
CACHE_IMAGE(PRINT, print, path);
CACHE_IMAGE(QUIT, quit, path);
CACHE_IMAGE(CUT, cut, path);
CACHE_IMAGE(COPY, copy, path);
CACHE_IMAGE(PASTE, paste, path);
CACHE_IMAGE(DELETE, delete, path);
CACHE_IMAGE(SELECTALL, selectall, path);
CACHE_IMAGE(PREFERENCES, preferences, path);
CACHE_IMAGE(ZOOMPLUS, zoomplus, path);
CACHE_IMAGE(ZOOMMINUS, zoomminus, path);
CACHE_IMAGE(ZOOMNORMAL, zoomnormal, path);
CACHE_IMAGE(FULLSCREEN, fullscreen, path);
CACHE_IMAGE(VIEWSOURCE, viewsource, path);
CACHE_IMAGE(CONTENTS, helpcontents, path);
CACHE_IMAGE(ABOUT, helpabout, path);
CACHE_IMAGE(PDF, pdf, path);
CACHE_IMAGE(PLAINTEXT, plaintext, path);
CACHE_IMAGE(DRAWFILE, drawfile, path);
CACHE_IMAGE(POSTSCRIPT, postscript, path);
CACHE_IMAGE(FIND, find, path);
CACHE_IMAGE(DOWNLOADS, downloads, path);
CACHE_IMAGE(SAVEWINDOWSIZE, savewindowsize, path);
CACHE_IMAGE(TOGGLEDEBUGGING, toggledebugging, path);
CACHE_IMAGE(SAVEBOXTREE, boxtree, path);
CACHE_IMAGE(SAVEDOMTREE, domtree, path);
CACHE_IMAGE(LOCALHISTORY, localhistory, path);
CACHE_IMAGE(GLOBALHISTORY, globalhistory, path);
CACHE_IMAGE(ADDBOOKMARKS, addbookmarks, path);
CACHE_IMAGE(SHOWBOOKMARKS, showbookmarks, path);
CACHE_IMAGE(OPENLOCATION, openlocation, path);
CACHE_IMAGE(NEXTTAB, nexttab, path);
CACHE_IMAGE(PREVTAB, prevtab, path);
CACHE_IMAGE(GUIDE, helpguide, path);
CACHE_IMAGE(INFO, helpinfo, path);
#undef CACHE_IMAGE
#define CACHE_IMAGE(p, q, r)\
nsgtk_theme_cache_searchimage(p, #q ".png", r);
CACHE_IMAGE(SEARCH_BACK_BUTTON, searchback, path);
CACHE_IMAGE(SEARCH_FORWARD_BUTTON, searchforward, path);
CACHE_IMAGE(SEARCH_CLOSE_BUTTON, searchclose, path);
#undef CACHE_IMAGE
}
/**
* returns default image for buttons / menu items from gtk stock items
* \param i button reference
*/
GtkImage *nsgtk_theme_image_default(nsgtk_toolbar_button i, GtkIconSize s)
{
char *imagefile;
GtkImage *image;
switch(i) {
#define BUTTON_IMAGE(p, q)\
case p##_BUTTON:\
return GTK_IMAGE(gtk_image_new_from_stock(#q, s))
BUTTON_IMAGE(BACK, gtk-go-back);
case HISTORY_BUTTON: {
size_t len = SLEN("arrow_down_8x32.png") +
strlen(res_dir_location) + 1;
imagefile = malloc(len);
if (imagefile == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
snprintf(imagefile, len, "%sarrow_down_8x32.png",
res_dir_location);
image = GTK_IMAGE(gtk_image_new_from_file(imagefile));
free(imagefile);
return image;
}
BUTTON_IMAGE(FORWARD, gtk-go-forward);
BUTTON_IMAGE(STOP, gtk-stop);
BUTTON_IMAGE(RELOAD, gtk-refresh);
BUTTON_IMAGE(HOME, gtk-home);
BUTTON_IMAGE(NEWWINDOW, gtk-new);
BUTTON_IMAGE(NEWTAB, gtk-new);
BUTTON_IMAGE(OPENFILE, gtk-open);
BUTTON_IMAGE(CLOSETAB, gtk-close);
BUTTON_IMAGE(CLOSEWINDOW, gtk-close);
BUTTON_IMAGE(SAVEPAGE, gtk-save-as);
BUTTON_IMAGE(PRINTPREVIEW, gtk-print-preview);
BUTTON_IMAGE(PRINT, gtk-print);
BUTTON_IMAGE(QUIT, gtk-quit);
BUTTON_IMAGE(CUT, gtk-cut);
BUTTON_IMAGE(COPY, gtk-copy);
BUTTON_IMAGE(PASTE, gtk-paste);
BUTTON_IMAGE(DELETE, gtk-delete);
BUTTON_IMAGE(SELECTALL, gtk-select-all);
BUTTON_IMAGE(FIND, gtk-find);
BUTTON_IMAGE(PREFERENCES, gtk-preferences);
BUTTON_IMAGE(ZOOMPLUS, gtk-zoom-in);
BUTTON_IMAGE(ZOOMMINUS, gtk-zoom-out);
BUTTON_IMAGE(ZOOMNORMAL, gtk-zoom-100);
BUTTON_IMAGE(FULLSCREEN, gtk-fullscreen);
BUTTON_IMAGE(VIEWSOURCE, gtk-index);
BUTTON_IMAGE(CONTENTS, gtk-help);
BUTTON_IMAGE(ABOUT, gtk-about);
#undef BUTTON_IMAGE
case (PLACEHOLDER_BUTTON + SEARCH_BACK_BUTTON):
return GTK_IMAGE(gtk_image_new_from_stock("gtk-go-back", s));
case (PLACEHOLDER_BUTTON + SEARCH_FORWARD_BUTTON):
return GTK_IMAGE(gtk_image_new_from_stock("gtk-go-forward",
s));
case (PLACEHOLDER_BUTTON + SEARCH_CLOSE_BUTTON):
return GTK_IMAGE(gtk_image_new_from_stock("gtk-close", s));
default: {
size_t len = SLEN("themes/Alpha.png") +
strlen(res_dir_location) + 1;
imagefile = malloc(len);
if (imagefile == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
snprintf(imagefile, len, "%sthemes/Alpha.png",
res_dir_location);
image = GTK_IMAGE(
gtk_image_new_from_file(imagefile));
free(imagefile);
return image;
}
}
}
#ifdef WITH_THEME_INSTALL
/**
* when CONTENT_THEME needs handling call this function
*/
void theme_install_start(struct content *c)
{
assert(c);
assert(c->type == CONTENT_THEME);
/* stop theme sitting in memory cache */
c->fresh = false;
if (!content_add_user(c, theme_install_callback, 0, 0)) {
warn_user("NoMemory", 0);
return;
}
}
/**
* Callback for fetchcache() for theme install fetches.
*/
void theme_install_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data)
{
switch (msg) {
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
theme_install_content = c;
if (!theme_install_read(c->source_data, c->source_size))
warn_user("ThemeInvalid", 0);
break;
case CONTENT_MSG_ERROR:
warn_user(data.error, 0);
break;
case CONTENT_MSG_STATUS:
break;
case CONTENT_MSG_LOADING:
case CONTENT_MSG_REFORMAT:
case CONTENT_MSG_REDRAW:
case CONTENT_MSG_NEWPTR:
case CONTENT_MSG_LAUNCH:
case CONTENT_MSG_AUTH:
default:
assert(0);
break;
}
}
/**
* handler saves theme data content as a local theme
*/
bool theme_install_read(const char *data, unsigned long len)
{
char *filename, *newfilename;
size_t namelen;
int handle = g_file_open_tmp("nsgtkthemeXXXXXX", &filename, NULL);
if (handle == -1) {
warn_user(messages_get("gtkFileError"),
"temporary theme file");
}
ssize_t written = write(handle, data, len);
close(handle);
if ((unsigned)written != len)
return false;
/* get name of theme; set as dirname */
namelen = SLEN("themes/") + strlen(res_dir_location) + 1;
char dirname[namelen];
snprintf(dirname, namelen, "%sthemes/", res_dir_location);
/* save individual files in theme */
newfilename = container_extract_theme(filename, dirname);
g_free(filename);
if (newfilename == NULL)
return false;
nsgtk_theme_add(newfilename);
free(newfilename);
return true;
}
#endif
/**
* loads the set of default images for the toolbar / menus
*/
struct nsgtk_theme *nsgtk_theme_default(GtkIconSize s)
{
struct nsgtk_theme *theme = malloc(sizeof(struct nsgtk_theme));
if (theme == NULL) {
warn_user("NoMemory", 0);
return NULL;
}
for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON +
SEARCH_BUTTONS_COUNT; i++)
theme->image[i] = nsgtk_theme_image_default(i, s);
return theme;
}

46
gtk/gtk_theme.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_GTK_THEME_H_
#define _NETSURF_GTK_THEME_H_
#include <gtk/gtk.h>
#include "gtk/gtk_scaffolding.h"
typedef enum search_buttons {
SEARCH_BACK_BUTTON = 0,
SEARCH_FORWARD_BUTTON,
SEARCH_CLOSE_BUTTON,
SEARCH_BUTTONS_COUNT
} nsgtk_search_buttons;
struct nsgtk_theme {
GtkImage *image[PLACEHOLDER_BUTTON];
GtkImage *searchimage[SEARCH_BUTTONS_COUNT];
/* apng throbber element */
};
struct nsgtk_theme *nsgtk_theme_load(GtkIconSize s);
void nsgtk_theme_add(const char *themename);
void nsgtk_theme_init(void);
void nsgtk_theme_prepare(void);
void nsgtk_theme_implement(struct gtk_scaffolding *g);
char *nsgtk_theme_name(void);
void nsgtk_theme_set_name(char *name);
#endif

1102
gtk/gtk_toolbar.c Normal file

File diff suppressed because it is too large Load Diff

90
gtk/gtk_toolbar.h Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NETSURF_GTK_TOOLBAR_H_
#define _NETSURF_GTK_TOOLBAR_H_
#include <gtk/gtk.h>
#include "gtk/gtk_scaffolding.h"
void nsgtk_toolbar_customization_init(nsgtk_scaffolding *g);
void nsgtk_toolbar_init(nsgtk_scaffolding *g);
void nsgtk_toolbar_customization_load(nsgtk_scaffolding *g);
void nsgtk_toolbar_set_physical(nsgtk_scaffolding *g);
void nsgtk_toolbar_connect_all(nsgtk_scaffolding *g);
int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget, nsgtk_scaffolding
*g);
#define TOOLPROTO(q) gboolean nsgtk_toolbar_##q##_button_data(\
GtkWidget *widget, GdkDragContext *cont, GtkSelectionData\
*selection, guint info, guint time, gpointer data);\
gboolean nsgtk_toolbar_##q##_toolbar_button_data(GtkWidget *widget,\
GdkDragContext *cont, GtkSelectionData *selection, guint info,\
guint time, gpointer data)
TOOLPROTO(home);
TOOLPROTO(back);
TOOLPROTO(forward);
TOOLPROTO(reload);
TOOLPROTO(stop);
TOOLPROTO(throbber);
TOOLPROTO(websearch);
TOOLPROTO(history);
TOOLPROTO(newwindow);
TOOLPROTO(newtab);
TOOLPROTO(openfile);
TOOLPROTO(closetab);
TOOLPROTO(closewindow);
TOOLPROTO(savepage);
TOOLPROTO(pdf);
TOOLPROTO(plaintext);
TOOLPROTO(drawfile);
TOOLPROTO(postscript);
TOOLPROTO(printpreview);
TOOLPROTO(print);
TOOLPROTO(quit);
TOOLPROTO(cut);
TOOLPROTO(copy);
TOOLPROTO(paste);
TOOLPROTO(delete);
TOOLPROTO(selectall);
TOOLPROTO(find);
TOOLPROTO(preferences);
TOOLPROTO(zoomplus);
TOOLPROTO(zoomminus);
TOOLPROTO(zoomnormal);
TOOLPROTO(fullscreen);
TOOLPROTO(viewsource);
TOOLPROTO(downloads);
TOOLPROTO(localhistory);
TOOLPROTO(globalhistory);
TOOLPROTO(addbookmarks);
TOOLPROTO(showbookmarks);
TOOLPROTO(openlocation);
TOOLPROTO(nexttab);
TOOLPROTO(prevtab);
TOOLPROTO(savewindowsize);
TOOLPROTO(toggledebugging);
TOOLPROTO(saveboxtree);
TOOLPROTO(savedomtree);
TOOLPROTO(contents);
TOOLPROTO(guide);
TOOLPROTO(info);
TOOLPROTO(about);
#undef TOOLPROTO
#endif

View File

@ -22,6 +22,7 @@
#include "gtk/gtk_window.h"
#include "desktop/browser.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
#include "desktop/textinput.h"
#include "desktop/selection.h"
#include "gtk/gtk_gui.h"
@ -35,7 +36,36 @@
#include <gdk/gdkkeysyms.h>
#include <assert.h>
struct gui_window *window_list = 0; /**< first entry in win list*/
struct gui_window {
/* All gui_window objects have an ultimate scaffold */
nsgtk_scaffolding *scaffold;
/**< the gtk object containing menu, buttons, url bar, [tabs],
* drawing area, etc that may contain 1 -> several gui_windows */
struct browser_window *bw;
/**< the 'content' window that is rendered in the gui_window*/
struct browser_mouse *mouse; /**< contains mouse state / events */
int caretx, carety, careth;
/**< storage caret dimension / location for rendering */
gui_pointer_shape current_pointer;
/**< storage caret shape for rendering */
int last_x, last_y;
/**< storage caret location for rendering */
GtkScrolledWindow *scrolledwindow;
/**< optional; for frames that need it; top level of gtk structure of
* gui_window */
GtkViewport *viewport;
/**< contained in a scrolled window */
GtkFixed *fixed; /**< contained in a viewport */
GtkDrawingArea *drawing_area; /**< contained in a gtkfixed */
GtkWidget *tab; /** the visible tab */
gulong signalhandler[NSGTK_WINDOW_SIGNAL_COUNT];
/**< to allow disactivation / resume of normal window behaviour */
struct gui_window *next, *prev; /**< list for eventual cleanup */
};
struct gui_window *window_list = NULL; /**< first entry in win list*/
int temp_open_background = -1;
@ -60,19 +90,45 @@ static void nsgtk_redraw_caret(struct gui_window *g);
static GdkCursor *nsgtk_create_menu_cursor(void);
struct browser_window *nsgtk_get_browser_window(struct gui_window *g)
{
return g->bw;
}
nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g)
{
return g->scaffold;
}
struct browser_window *nsgtk_get_browser_for_gui(struct gui_window *g)
struct browser_window *gui_window_get_browser_window(struct gui_window *g)
{
return g->bw;
return g->bw;
}
unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i)
{
return g->signalhandler[i];
}
GtkDrawingArea *nsgtk_window_get_drawing_area(struct gui_window *g)
{
return g->drawing_area;
}
GtkScrolledWindow *nsgtk_window_get_scrolledwindow(struct gui_window *g)
{
return g->scrolledwindow;
}
GtkWidget *nsgtk_window_get_tab(struct gui_window *g)
{
return g->tab;
}
void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w)
{
g->tab = w;
}
struct gui_window *nsgtk_window_iterate(struct gui_window *g)
{
return g->next;
}
float nsgtk_get_scale_for_gui(struct gui_window *g)
@ -111,13 +167,6 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
g->careth = 0;
/* Attach ourselves to the list (push_top) */
if (window_list)
window_list->prev = g;
g->next = window_list;
g->prev = NULL;
window_list = g;
if (bw->parent != NULL)
/* Find our parent's scaffolding */
g->scaffold = bw->parent->window->scaffold;
@ -127,9 +176,20 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
else
/* Now construct and attach a scaffold */
g->scaffold = nsgtk_new_scaffolding(g);
if (g->scaffold == NULL) {
free(g);
return NULL;
}
/* Construct our primary elements */
g->fixed = GTK_FIXED(gtk_fixed_new());
/* Attach ourselves to the list (push_top) */
if (window_list)
window_list->prev = g;
g->next = window_list;
g->prev = NULL;
window_list = g;
/* Construct our primary elements */
g->fixed = GTK_FIXED(gtk_fixed_new());
g->drawing_area = GTK_DRAWING_AREA(gtk_drawing_area_new());
gtk_fixed_put(g->fixed, GTK_WIDGET(g->drawing_area), 0, 0);
gtk_container_set_border_width(GTK_CONTAINER(g->fixed), 0);
@ -219,6 +279,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK);
GTK_WIDGET_SET_FLAGS(GTK_WIDGET(g->drawing_area), GTK_CAN_FOCUS);
@ -229,17 +290,20 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
#define CONNECT(obj, sig, callback, ptr) \
g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
CONNECT(g->drawing_area, "expose_event", nsgtk_window_expose_event, g);
g->signalhandler[NSGTK_WINDOW_SIGNAL_REDRAW] =
CONNECT(g->drawing_area, "expose_event",
nsgtk_window_expose_event, g);
CONNECT(g->drawing_area, "motion_notify_event",
nsgtk_window_motion_notify_event, g);
CONNECT(g->drawing_area, "button_press_event",
nsgtk_window_button_press_event, g);
nsgtk_window_motion_notify_event, g);
g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] =
CONNECT(g->drawing_area, "button_press_event",
nsgtk_window_button_press_event, g);
CONNECT(g->drawing_area, "button_release_event",
nsgtk_window_button_release_event, g);
nsgtk_window_button_release_event, g);
CONNECT(g->drawing_area, "key_press_event",
nsgtk_window_keypress_event, g);
nsgtk_window_keypress_event, g);
CONNECT(g->viewport, "size_allocate",
nsgtk_window_size_allocate_event, g);
nsgtk_window_size_allocate_event, g);
return g;
}
@ -344,7 +408,9 @@ gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
struct gui_window *g = data;
bool shift = event->state & GDK_SHIFT_MASK;
bool ctrl = event->state & GDK_CONTROL_MASK;
if ((abs(event->x - g->last_x) < 5) && (abs(event->y - g->last_y) < 5))
/* necessary for touch screens */
return FALSE;
if (g->mouse->state & BROWSER_MOUSE_PRESS_1){
/* Start button 1 drag */
browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_1,
@ -384,29 +450,24 @@ gboolean nsgtk_window_button_press_event(GtkWidget *widget,
struct gui_window *g = data;
gtk_widget_grab_focus(GTK_WIDGET(g->drawing_area));
gtk_widget_hide(GTK_WIDGET(nsgtk_scaffolding_history_window(
g->scaffold)->window));
g->mouse->pressed_x = event->x / g->bw->scale;
g->mouse->pressed_y = event->y / g->bw->scale;
if (event->button == 3) {
/** \todo
* Firstly, MOUSE_PRESS_2 on GTK is a middle click, which doesn't
* appear correct to me. Secondly, right-clicks are not passed to
* browser_window_mouse_click() at all, which also seems incorrect
* since they should result in browser_window_remove_caret().
*
* I would surmise we need a MOUSE_PRESS_3, unless right-clicking is
* supposed to be mapped to MOUSE_PRESS_2, but that doesn't appear
* correct either.
*/
browser_window_remove_caret(g->bw);
nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse->pressed_x, g->mouse->pressed_y);
return TRUE;
}
switch (event->button) {
case 1: g->mouse->state = BROWSER_MOUSE_PRESS_1; break;
case 2: g->mouse->state = BROWSER_MOUSE_PRESS_2; break;
case 1:
g->mouse->state = BROWSER_MOUSE_PRESS_1;
break;
case 3:
browser_window_remove_caret(g->bw);
nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse->pressed_x,
g->mouse->pressed_y);
g->mouse->state = BROWSER_MOUSE_PRESS_2;
break;
default:
return FALSE;
}
/* Handle the modifiers too */
if (event->state & GDK_SHIFT_MASK)
@ -565,7 +626,7 @@ void nsgtk_reflow_all_windows(void)
{
for (struct gui_window *g = window_list; g; g = g->next) {
nsgtk_tab_options_changed(GTK_WIDGET(
nsgtk_scaffolding_get_notebook(g)));
nsgtk_scaffolding_notebook(g->scaffold)));
g->bw->reformat_pending = true;
}
@ -702,6 +763,12 @@ void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
gtk_adjustment_set_value(hadj, x);
}
void gui_window_scroll_visible(struct gui_window *g, int x0, int y0,
int x1, int y1)
{
gui_window_set_scroll(g,x0,y0);
}
/**
* Set the scale setting of a window

View File

@ -23,36 +23,6 @@
#include "desktop/browser.h"
#include "gtk/gtk_scaffolding.h"
struct gui_window {
/* All gui_window objects have an ultimate scaffold */
nsgtk_scaffolding *scaffold;
/* A gui_window is the rendering of a browser_window */
struct browser_window *bw;
struct browser_mouse *mouse;
/* These are the storage for the rendering */
int caretx, carety, careth;
gui_pointer_shape current_pointer;
int last_x, last_y;
/* Within GTK, a gui_window is a scrolled window
* with a viewport inside
* with a gtkfixed in that
* with a drawing area in that
* The scrolled window is optional and only chosen
* for frames which need it. Otherwise we just use
* a viewport.
*/
GtkWidget *tab;
GtkScrolledWindow *scrolledwindow;
GtkViewport *viewport;
GtkFixed *fixed;
GtkDrawingArea *drawing_area;
/* Keep gui_windows in a list for cleanup later */
struct gui_window *next, *prev;
};
struct browser_mouse {
struct gui_window *gui;
struct box *box;
@ -63,19 +33,29 @@ struct browser_mouse {
browser_mouse_state state;
};
extern struct gui_window * window_list;
typedef enum nsgtk_window_signals {
NSGTK_WINDOW_SIGNAL_CLICK,
NSGTK_WINDOW_SIGNAL_REDRAW,
NSGTK_WINDOW_SIGNAL_COUNT
} nsgtk_window_signal;
extern struct gui_window *window_list;
extern int temp_open_background;
void nsgtk_reflow_all_windows(void);
void nsgtk_window_process_reformats(void);
nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g);
struct browser_window *nsgtk_get_browser_for_gui(struct gui_window *g);
float nsgtk_get_scale_for_gui(struct gui_window *g);
int nsgtk_gui_window_update_targets(struct gui_window *g);
void nsgtk_window_destroy_browser(struct gui_window *g);
unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i);
GtkDrawingArea *nsgtk_window_get_drawing_area(struct gui_window *g);
struct gui_window *nsgtk_window_iterate(struct gui_window *g);
GtkScrolledWindow *nsgtk_window_get_scrolledwindow(struct gui_window *g);
GtkWidget *nsgtk_window_get_tab(struct gui_window *g);
void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w);
struct browser_window *nsgtk_get_browser_window(struct gui_window *g);
#endif /* NETSURF_GTK_WINDOW_H */

View File

@ -34,6 +34,8 @@ extern int option_history_age;
extern bool option_hover_urls;
extern bool option_focus_new;
extern bool option_new_blank;
extern bool option_source_tab;
extern int option_current_theme;
#define EXTRA_OPTION_DEFINE \
bool option_render_resample = false; \
@ -48,7 +50,9 @@ bool option_disable_plugins = false; \
int option_history_age = 0; \
bool option_hover_urls = false; \
bool option_focus_new = false; \
bool option_new_blank = false;
bool option_new_blank = false; \
bool option_source_tab = false;\
int option_current_theme = 0;
#define EXTRA_OPTION_TABLE \
{ "render_resample", OPTION_BOOL, &option_render_resample }, \
@ -63,6 +67,8 @@ bool option_new_blank = false;
{ "history_age", OPTION_INTEGER, &option_history_age}, \
{ "hover_urls", OPTION_BOOL, &option_hover_urls}, \
{ "focus_new", OPTION_BOOL, &option_focus_new}, \
{ "new_blank", OPTION_BOOL, &option_new_blank}
{ "new_blank", OPTION_BOOL, &option_new_blank}, \
{ "source_tab", OPTION_BOOL, &option_source_tab},\
{ "current_theme", OPTION_INTEGER, &option_current_theme}
#endif

20
gtk/res/SearchEngines Normal file
View File

@ -0,0 +1,20 @@
Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|
Yahoo|search.yahoo.com|http://search.yahoo.com/search?p=%s|http://www.yahoo.com/favicon.ico|
Bing|www.bing.com|http://www.bing.com/search?q=%s|http://www.bing.com/favicon.ico|
Business.com|www.business.com|http://www.business.com/search/rslt_default.asp?query=%s|http://www.business.com/favicon.ico|
Omgili|www.omgili.com|http://www.omgili.com/AAAAA/%s.html|http://www.omgili.com/favicon.ico|
BBC News|search.bbc.co.uk|http://search.bbc.co.uk/search?q=%s&tab=ns|http://news.bbc.co.uk/favicon.ico|
Ubuntu Packages|packages.ubuntu.com|http://packages.ubuntu.com/search?keywords=%s|http://packages.ubuntu.com/favicon.ico|
Creative Commons|creativecommons.org|http://creativecommons.org/?s=%s|http://creativecommons.org/favicon.ico|
Ask.com|www.ask.com|http://www.ask.com/web?q=%s|http://www.ask.com/favicon.ico|
Answers.com|www.answers.com|http://www.answers.com/%s|http://www.answers.com/favicon.ico|
Dictionary.com|dictionary.reference.com|http://dictionary.reference.com/browse/%s?jss=0|http://dictionary.reference.com/favicon.ico|
Youtube|www.youtube.com|http://www.youtube.com/results?search_query=%s|http://www.youtube.com/favicon.ico|
AeroMp3|www.aeromp3.com|http://www.aeromp3.com/search?q=%s|http://www.aeromp3.com/favicon.ico|
AOL|search.aol.com|http://search.aol.com/aol/search?query=%s|http://www.aol.com/favicon.ico|
Baidu|www.baidu.com|http://www.baidu.com/s?wd=%s|http://www.baidu.com/favicon.ico|
Amazon|www.amazon.com|http://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|http://www.amazon.com/favicon.ico|
Ebay|shop.ebay.com|http://shop.ebay.com/items/%s|http://www.ebay.com/favicon.ico|
IMDB|www.imdb.com|http://www.imdb.com/find?q=%s|http://www.imdb.com/favicon.ico|
ESPN|search.espn.go.com|http://search.espn.go.com/%s/|http://www.espn.go.com/favicon.ico|
Wikipedia|en.wikipedia.org|http://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|http://en.wikipedia.org/favicon.ico|

BIN
gtk/res/default.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
gtk/res/html.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

222
gtk/res/login.glade Normal file
View File

@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkDialog" id="wndLogin">
<property name="title" translatable="yes">Site Authentication</property>
<property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<child>
<widget class="GtkHBox" id="hbox12">
<property name="visible">True</property>
<property name="border_width">3</property>
<child>
<widget class="GtkImage" id="image3">
<property name="visible">True</property>
<property name="yalign">0.10000000149011612</property>
<property name="xpad">12</property>
<property name="icon_size">6</property>
<property name="icon_name">gtk-dialog-authentication</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table5">
<property name="visible">True</property>
<property name="border_width">1</property>
<property name="n_rows">4</property>
<property name="n_columns">2</property>
<property name="column_spacing">11</property>
<property name="row_spacing">10</property>
<child>
<widget class="GtkLabel" id="labelLoginHost">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">moo.yoo.com</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label57">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Password</property>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label56">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Username</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label54">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Host</property>
</widget>
<packing>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label55">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Realm</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="labelLoginRealm">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">my sekr3t area</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryLoginPass">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="activates_default">True</property>
<property name="text" translatable="yes">opensesame</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryLoginUser">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="text" translatable="yes">sesame</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="padding">1</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="buttonLoginCan">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">-6</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="buttonLoginOK">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="response_id">-5</property>
<child>
<widget class="GtkAlignment" id="alignment14">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox11">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="stock">gtk-ok</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label49">
<property name="visible">True</property>
<property name="label" translatable="yes">Login</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

274
gtk/res/password.glade Normal file
View File

@ -0,0 +1,274 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkWindow" id="wndPDFPassword">
<property name="title" translatable="yes">PDF Password</property>
<property name="modal">True</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="yalign">0.10000000149011612</property>
<property name="xpad">12</property>
<property name="icon_size">6</property>
<property name="icon_name">gtk-dialog-authentication</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkLabel" id="labelInfo">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Write and confirm passwords:</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">Owner password:</property>
<property name="width_chars">15</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryPDFOwnerPassword">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">20</property>
<property name="visibility">False</property>
<property name="width_chars">20</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="label" translatable="yes">Repeat password:</property>
<property name="width_chars">15</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryPDFOwnerPassword1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">20</property>
<property name="visibility">False</property>
<property name="width_chars">20</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">User password:</property>
<property name="width_chars">15</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryPDFUserPassword">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">20</property>
<property name="visibility">False</property>
<property name="width_chars">20</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="label" translatable="yes">Repeat password:</property>
<property name="width_chars">15</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryPDFUserPassword1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">20</property>
<property name="visibility">False</property>
<property name="width_chars">20</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="spacing">10</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="buttonPDFSetPassword">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="response_id">0</property>
<child>
<widget class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="image7">
<property name="visible">True</property>
<property name="stock">gtk-ok</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="label" translatable="yes">Set password</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkButton" id="buttonPDFNoPassword">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="response_id">0</property>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<child>
<widget class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="image8">
<property name="visible">True</property>
<property name="stock">gtk-cancel</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">No password</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

197
gtk/res/ssl.glade Normal file
View File

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkDialog" id="wndSSLProblem">
<property name="border_width">1</property>
<property name="title" translatable="yes">SSL certificate problem</property>
<property name="modal">True</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<child>
<widget class="GtkHBox" id="hbox15">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="image6">
<property name="visible">True</property>
<property name="yalign">0</property>
<property name="icon_size">6</property>
<property name="icon_name">gtk-dialog-warning</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox13">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="label62">
<property name="visible">True</property>
<property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<property name="wrap">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame13">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="label_xalign">0</property>
<child>
<widget class="GtkAlignment" id="alignment17">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkTextView" id="textview1">
<property name="height_request">200</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="text" translatable="yes">(not implemented)</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label63">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Certificate chain&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="sslreject">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="response_id">-6</property>
<child>
<widget class="GtkAlignment" id="alignment16">
<property name="visible">True</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox14">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image5">
<property name="visible">True</property>
<property name="stock">gtk-cancel</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label61">
<property name="visible">True</property>
<property name="label" translatable="yes">Reject</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkButton" id="sslaccept">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="response_id">-5</property>
<child>
<widget class="GtkAlignment" id="alignment15">
<property name="visible">True</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox13">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image4">
<property name="visible">True</property>
<property name="stock">gtk-apply</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label60">
<property name="visible">True</property>
<property name="label" translatable="yes">Accept</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

2
gtk/res/themelist Normal file
View File

@ -0,0 +1,2 @@
gtk default theme
gtk+

BIN
gtk/res/themes/Alpha.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

BIN
gtk/res/themes/gtk+/cut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

81
gtk/res/themes/gtk+/info Normal file
View File

@ -0,0 +1,81 @@
This file is part of NetSurf, http://www.netsurf-browser.org/
The images in this theme folder 'gtk+' are from the gtk stock image set
http://library.gnome.org/devel/gtk/unstable/gtk-Stock-Items.html
the image history.png is [for what it's worth!] Copyright 2009 Mark Benjamin
<netsurf-browser.org.MarkBenjamin@dfgh.net>
NetSurf is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
NetSurf is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*** Instructions for theming ***
to create a theme, make a folder, whose name is the name of the theme;
put in the folder, a set of png images for the toolbuttons;
the names of the images should be a subset of the list
back.png,
history.png,
forward.png,
stop.png,
reload.png,
home.png,
newwindow.png,
newtab.png,
openfile.png,
closetab.png,
closewindow.png,
savepage.png,
pdf.png,
plaintext.png,
drawfile.png,
postscript.png,
printpreview.png,
print.png,
quit.png,
cut.png,
copy.png,
paste.png,
delete.png,
selectall.png,
find.png,
preferences.png,
zoomplus.png,
zoomminus.png,
zoomnormal.png,
fullscreen.png,
viewsource.png,
downloads.png,
savewindowsize.png,
toggledebugging.png,
saveboxtree.png,
savedomtree.png,
localhistory.png,
globalhistory.png,
addbookmarks.png,
showbookmarks.png,
openlocation.png,
nexttab.png,
prevtab.png,
contents.png,
guide.png,
info.png,
about.png,
searchback.png,
searchforward.png,
searchclose.png
for local theming, the folder may be placed directly [as a subfolder] into the netsurf/gtk/res/themes folder; then 'add theme' from the preferences->advanced tab;
for downloadable themes, compile netsurf/utils/container.c according to the instructions in the header of that file; make a netsurf container of the folder, serve it as content-type "application/x-netsurf-theme"; browse to it in NetSurf, then NetSurf should automatically install it

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Some files were not shown because too many files have changed in this diff Show More