* src/rtl/hbsocket.c
! hb_socketSetReuseAddr() changed on win platforms to use
SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR. See http://paste.lisp.org/display/59751.
Rough patch, maybe the logic isn't applied to the right place,
maybe extra win version checks are required, please test it
and patch it further if needed.
* src/rtl/hbinet.c
* s_inetBind() changed back to call hb_socketSetReuseAddr() also
on win platforms.
* contrib/hbwin/tests/testole.prg
+ Added shortcut creation example.
* contrib/hbide/idemisc.prg
! Fixed HBIDE_PATHNORMALIZED() to _never_ lowercase passed
filename. As discussed very long time ago, such behavior
is not portable. For comparison purposes HB_FILEMATCH()
should be used, for other purposes _no_ change should be
done by hbide in filename casing. Ever.
This is brute force fix only applied to low-level code.
It will cause regressions on the higher level, which have
to be fixed.
; TODO: Delete this second parameter from all calls, now
the value is ignored.
; TOFIX: Review all
HBIDE_PATHNORMALIZED() and
HBIDE_PATHNORMALIZED( p, .T. )
calls if they are used in comparison context and change
caller code to use HB_FILEMATCH().
; TOFIX: All current code which uses LOWER()/UPPER() to
"normalize" filename before comparison with '=='
operator should also be changed to HB_FILEMATCH().
(except for cases where extension is used in the
sense of file type).
; TOFIX: Rest of cases where LOWER()/UPPER() is applied to
filenames.
! Fixed HBIDE_PATHFILE() to never uppercase drive letter.
It's not strictly required since all so far known systems
supporting drive letter are case insensitive, but it's
nevertheless not the job of hbide to reformat pathnames.
* contrib/hbide/ideactions.prg
* contrib/hbide/idesaveload.prg
* contrib/hbide/ideharbourhelp.prg
* contrib/hbide/ideeditor.prg
* contrib/hbide/ideprojmanager.prg
* contrib/hbide/idesources.prg
! Fixed some code to use HB_FILEMATCH() instead of unconditional
uppercasing/lowercasing. Please review and finish this modification,
there might be more hidden places and might have overlooked anything
in this patch.
522 lines
16 KiB
Plaintext
522 lines
16 KiB
Plaintext
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
*
|
|
* Copyright 2010 Pritpal Bedi <pritpal@vouchcac.com>
|
|
* www - http://harbour-project.org
|
|
*
|
|
* This program 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; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program 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 software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
/*----------------------------------------------------------------------*/
|
|
/*----------------------------------------------------------------------*/
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* EkOnkar
|
|
* ( The LORD is ONE )
|
|
*
|
|
* Harbour-Qt IDE
|
|
*
|
|
* Pritpal Bedi <pritpal@vouchcac.com>
|
|
* 09Jan2010
|
|
*/
|
|
/*----------------------------------------------------------------------*/
|
|
/*----------------------------------------------------------------------*/
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#include "common.ch"
|
|
#include "hbclass.ch"
|
|
#include "hbqtgui.ch"
|
|
#include "hbide.ch"
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
CLASS IdeSourcesManager INHERIT IdeObject
|
|
|
|
METHOD new( oIde )
|
|
METHOD create( oIde )
|
|
METHOD loadSources()
|
|
METHOD saveSource( nTab, lCancel, lAs )
|
|
METHOD saveNamedSource( cSource )
|
|
METHOD editSource( cSourceFile, nPos, nHPos, nVPos, cTheme, cView, lAlert, lVisible, aBookMarks )
|
|
METHOD closeSource( nTab, lCanCancel, lCanceled )
|
|
METHOD closeAllSources( lCanCancel )
|
|
METHOD closeAllOthers( nTab )
|
|
METHOD saveAllSources()
|
|
METHOD saveAndExit()
|
|
METHOD revertSource( nTab )
|
|
METHOD openSource()
|
|
METHOD selectSource( cMode, cFile, cTitle, cDftPath )
|
|
|
|
ENDCLASS
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:new( oIde )
|
|
|
|
::oIde := oIde
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:create( oIde )
|
|
|
|
DEFAULT oIde TO ::oIde
|
|
|
|
::oIde := oIde
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:loadSources()
|
|
LOCAL a_
|
|
|
|
IF !empty( ::oIni:aFiles )
|
|
FOR EACH a_ IN ::oIni:aFiles
|
|
/* File nPos nVPos nHPos cTheme cView lAlert lVisible, aBookMarks */
|
|
::editSource( a_[ 1 ], a_[ 2 ], a_[ 3 ], a_[ 4 ], a_[ 5 ], a_[ 6 ], .t., .f., a_[ 7 ] )
|
|
NEXT
|
|
ENDIF
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:saveNamedSource( cSource )
|
|
LOCAL lSaved, oEditor, a_, cBuffer
|
|
|
|
cSource := hbide_pathNormalized( cSource, .t. )
|
|
|
|
FOR EACH a_ IN ::aTabs
|
|
oEditor := a_[ TAB_OEDITOR ]
|
|
IF hb_isObject( oEditor )
|
|
IF hb_FileMatch( hbide_pathNormalized( oEditor:sourceFile, .t. ), cSource )
|
|
IF oEditor:lLoaded
|
|
IF oEditor:qDocument:isModified()
|
|
cBuffer := oEditor:prepareBufferToSave( oEditor:qEdit:toPlainText() )
|
|
|
|
IF ( lSaved := hb_memowrit( hbide_pathToOSPath( cSource ), cBuffer ) )
|
|
oEditor:qDocument:setModified( .f. )
|
|
oEditor:setTabImage()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
NEXT
|
|
|
|
RETURN lSaved
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:editSource( cSourceFile, nPos, nHPos, nVPos, cTheme, cView, lAlert, lVisible, aBookMarks )
|
|
LOCAL lNew
|
|
|
|
DEFAULT lAlert TO .T.
|
|
DEFAULT lVisible TO .T.
|
|
|
|
IF ( lNew := empty( cSourceFile ) )
|
|
cSourceFile := hbide_saveAFile( ::oDlg, "Provide source filename", /*aFltr*/, hbide_SetWrkFolderLast(), /*cDftSuffix*/ )
|
|
IF empty( cSourceFile )
|
|
RETURN Self
|
|
ENDIF
|
|
hbide_SetWrkFolderLast( cSourceFile )
|
|
ENDIF
|
|
|
|
IF !Empty( cSourceFile )
|
|
IF !( hbide_isValidText( cSourceFile ) )
|
|
MsgBox( 'File type unknown or unsupported: ' + cSourceFile )
|
|
RETURN .f.
|
|
ELSEIF ! lNew .AND. ! hb_FileExists( cSourceFile )
|
|
MsgBox( 'File not found: ' + cSourceFile )
|
|
RETURN .f.
|
|
ENDIF
|
|
IF ::oEM:isOpen( cSourceFile )
|
|
IF lAlert
|
|
IF hbide_getYesNo( cSourceFile + " is already open.", ;
|
|
"Want to re-load it again ?", "File Open Info!" )
|
|
::oEM:reLoad( cSourceFile )
|
|
ENDIF
|
|
ENDIF
|
|
::oEM:setSourceVisible( cSourceFile )
|
|
RETURN .t.
|
|
ENDIF
|
|
ENDIF
|
|
|
|
DEFAULT nPos TO 0
|
|
DEFAULT nHPos TO 0
|
|
DEFAULT nVPos TO 0
|
|
|
|
::oEM:buildEditor( cSourceFile, nPos, nHPos, nVPos, cTheme, cView, aBookMarks )
|
|
IF lVisible
|
|
::oEM:setSourceVisible( cSourceFile )
|
|
ENDIF
|
|
|
|
IF !Empty( cSourceFile ) .AND. !hbide_isSourcePPO( cSourceFile )
|
|
hbide_mnuAddFileToMRU( Self, cSourceFile, "recent_files" )
|
|
ENDIF
|
|
|
|
RETURN .t.
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Save selected Tab on harddisk and return .T. if successfull!
|
|
*/
|
|
METHOD IdeSourcesManager:saveSource( nTab, lCancel, lAs )
|
|
LOCAL oEdit, lNew, cBuffer, qDocument, nIndex, cSource, cFileTemp
|
|
LOCAL cFileToSave, cFile, cExt, cNewFile, oItem
|
|
|
|
DEFAULT nTab TO ::EM:getTabCurrent()
|
|
DEFAULT lAs TO .F.
|
|
|
|
lCancel := .F.
|
|
|
|
IF !empty( oEdit := ::oEM:getEditorByTabPosition( nTab ) )
|
|
nIndex := ::qTabWidget:indexOf( oEdit:oTab:oWidget )
|
|
cSource := oEdit:sourceFile
|
|
|
|
// IF !Empty( oEdit:sourceFile ) .AND. oEdit:lLoaded .AND. oEdit:qDocument:isModified()
|
|
IF lAs .OR. empty( oEdit:sourceFile ) .OR. ( oEdit:lLoaded .AND. oEdit:qDocument:isModified() )
|
|
|
|
lNew := Empty( cSource ) .OR. lAs
|
|
IF lNew
|
|
cNewFile := ::selectSource( 'save', ;
|
|
iif( !Empty( cSource ), cSource, hb_dirBase() + "projects" + hb_ps() ),;
|
|
"Save " + oEdit:oTab:caption + " as..." )
|
|
IF empty( cNewFile )
|
|
// will check later what decision to take
|
|
RETURN .f.
|
|
ENDIF
|
|
IF hb_FileMatch( hbide_pathNormalized( cNewFile ), hbide_pathNormalized( cSource ) )
|
|
lNew := .f.
|
|
ENDIF
|
|
ENDIF
|
|
|
|
cFileToSave := iif( lNew, cNewFile, cSource )
|
|
qDocument := oEdit:qDocument
|
|
|
|
/*
|
|
* If the burn process fails, we should change the name of the previous file.
|
|
* 01/01/2010 - 21:24:41 - vailtom
|
|
*/
|
|
cBuffer := oEdit:prepareBufferToSave( oEdit:qEdit:toPlainText() )
|
|
//
|
|
IF !hb_memowrit( cFileToSave, cBuffer )
|
|
MsgBox( "Error saving the file " + oEdit:sourceFile + ".",, 'Error saving file!' )
|
|
lCancel := .T.
|
|
RETURN .F.
|
|
ENDIF
|
|
|
|
hb_fNameSplit( cFileToSave, , @cFile, @cExt )
|
|
|
|
IF lNew
|
|
oEdit:sourceFile := cFileToSave
|
|
|
|
oEdit:oTab:Caption := cFile + cExt
|
|
|
|
::qTabWidget:setTabText( nIndex, cFile + cExt )
|
|
::qTabWidget:setTabTooltip( nIndex, cFileToSave )
|
|
|
|
IF empty( cSource )
|
|
/* The file is not populated in editors tree. Inject */
|
|
::oEM:addSourceInTree( oEdit:sourceFile )
|
|
ELSEIF lAs
|
|
/* Rename the existing nodes in tree */
|
|
IF !empty( oItem := hbide_findProjTreeItem( ::oIde, oEdit:sourceFile, "Opened Source" ) )
|
|
oItem:oWidget:caption := cFile + cExt
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
qDocument:setModified( .f. )
|
|
::oIde:aSources := { oEdit:sourceFile }
|
|
::createTags()
|
|
::updateFuncList()
|
|
::qTabWidget:setTabIcon( nIndex, ::resPath + "tabunmodified.png" )
|
|
::oDK:setStatusText( SB_PNL_MODIFIED, " " )
|
|
|
|
cFileTemp := hbide_pathToOSPath( oEdit:cPath + oEdit:cFile + oEdit:cExt + ".tmp" )
|
|
ferase( cFileTemp )
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN .T.
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:closeSource( nTab, lCanCancel, lCanceled )
|
|
LOCAL lSave, n, oEditor
|
|
|
|
DEFAULT nTab TO ::oEM:getTabCurrent()
|
|
|
|
IF !empty( oEditor := ::oEM:getEditorByTabPosition( nTab ) )
|
|
|
|
DEFAULT lCanCancel TO .F.
|
|
lCanceled := .F.
|
|
|
|
IF !( oEditor:qDocument:isModified() ) /* File has not changed, ignore the question to User */
|
|
lSave := .F.
|
|
|
|
ELSEIF lCanCancel
|
|
n := hbide_getYesNoCancel( oEditor:oTab:Caption, "has been modified, save this source?", 'Save?' )
|
|
IF ( lCanceled := ( n == QMessageBox_Cancel ) )
|
|
RETURN .F.
|
|
ENDIF
|
|
lSave := ( n == QMessageBox_Yes )
|
|
|
|
ELSE
|
|
lSave := hbide_getYesNo( oEditor:oTab:Caption, "has been modified, save this source?", 'Save?' )
|
|
|
|
ENDIF
|
|
|
|
IF lSave .AND. !( ::saveSource( nTab, @lCanceled ) )
|
|
IF lCanCancel
|
|
RETURN .F.
|
|
ENDIF
|
|
ENDIF
|
|
|
|
oEditor:destroy()
|
|
::oIde:updateTitleBar()
|
|
ENDIF
|
|
|
|
RETURN .T.
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Close all opened files.
|
|
* 02/01/2010 - 15:31:44
|
|
*/
|
|
METHOD IdeSourcesManager:closeAllSources( lCanCancel )
|
|
LOCAL lCanceled
|
|
LOCAL i := 0
|
|
|
|
DEFAULT lCanCancel TO .t.
|
|
|
|
DO WHILE ( ++i <= Len( ::aTabs ) )
|
|
|
|
IF ::closeSource( i, lCanCancel, @lCanceled )
|
|
i --
|
|
LOOP
|
|
ENDIF
|
|
|
|
IF lCanceled
|
|
RETURN .F.
|
|
ENDIF
|
|
ENDDO
|
|
|
|
RETURN .T.
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Close all opened files except current.
|
|
* 02/01/2010 - 15:47:19 - vailtom
|
|
*/
|
|
METHOD IdeSourcesManager:closeAllOthers( nTab )
|
|
LOCAL lCanceled
|
|
LOCAL oEdit
|
|
LOCAL nID
|
|
|
|
DEFAULT nTab TO ::oEM:getTabCurrent()
|
|
|
|
IF empty( oEdit := ::oEM:getEditorByTabPosition( nTab ) )
|
|
RETURN .F.
|
|
ENDIF
|
|
|
|
nID := oEdit:nID
|
|
nTab := 0
|
|
|
|
* Finally now we will close all tabs.
|
|
DO WHILE ( ++nTab <= Len( ::aTabs ) )
|
|
|
|
oEdit := ::oEM:getEditorByTabPosition( nTab )
|
|
|
|
IF empty( oEdit ) .OR. oEdit:nID == nID
|
|
LOOP
|
|
ENDIF
|
|
|
|
IF ::closeSource( nTab, .T., @lCanceled )
|
|
nTab --
|
|
LOOP
|
|
ENDIF
|
|
|
|
IF lCanceled
|
|
RETURN .F.
|
|
ENDIF
|
|
ENDDO
|
|
|
|
RETURN .T.
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Save all opened files...
|
|
* 01/01/2010 - 22:44:36 - vailtom
|
|
*/
|
|
METHOD IdeSourcesManager:saveAllSources()
|
|
LOCAL n
|
|
|
|
FOR n := 1 TO Len( ::aTabs )
|
|
::saveSource( n )
|
|
NEXT
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Save current file and exits HBIDE
|
|
* 02/01/2010 - 18:45:06 - vailtom
|
|
*/
|
|
METHOD IdeSourcesManager:saveAndExit()
|
|
|
|
IF ::saveSource()
|
|
::execAction( "Exit" )
|
|
ENDIF
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/*
|
|
* Revert current file to a previous saved file.
|
|
* 02/01/2010 - 19:45:34
|
|
*/
|
|
METHOD IdeSourcesManager:revertSource( nTab )
|
|
LOCAL oEditor
|
|
|
|
DEFAULT nTab TO ::oEM:getTabCurrent()
|
|
|
|
IF empty( oEditor := ::oEM:getEditorByTabPosition( nTab ) )
|
|
RETURN .F.
|
|
ENDIF
|
|
|
|
IF !( oEditor:qDocument:isModified() )
|
|
* File has not changed, ignore the question to User
|
|
ELSE
|
|
IF !hbide_getYesNo( 'Revert ' + oEditor:oTab:Caption + '?', ;
|
|
'The file ' + oEditor:sourceFile + ' has changed. '+;
|
|
'Discard current changes and revert contents to the previously saved on disk?', 'Revert file?' )
|
|
RETURN Self
|
|
ENDIF
|
|
ENDIF
|
|
|
|
oEditor:qEdit:setPlainText( hb_memoRead( oEditor:sourceFile ) )
|
|
oEditor:qEdit:ensureCursorVisible()
|
|
::manageFocusInEditor()
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:openSource()
|
|
LOCAL aSrc, cSource
|
|
|
|
IF !empty( aSrc := ::selectSource( "openmany" ) )
|
|
FOR EACH cSource IN aSrc
|
|
::editSource( cSource )
|
|
NEXT
|
|
ENDIF
|
|
|
|
RETURN Self
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
METHOD IdeSourcesManager:selectSource( cMode, cFile, cTitle, cDftPath )
|
|
LOCAL oDlg, cPath
|
|
|
|
DEFAULT cDftPath TO ::cLastFileOpenPath
|
|
|
|
oDlg := XbpFileDialog():new():create( ::oDlg, , { 10,10 } )
|
|
|
|
IF cMode == "open"
|
|
oDlg:title := "Select a Source File"
|
|
oDlg:center := .t.
|
|
oDlg:fileFilters := { { "All Files" , "*.*" }, { "PRG Sources", "*.prg" }, { "C Sources" , "*.c" },;
|
|
{ "CPP Sources", "*.cpp" }, { "H Headers" , "*.h" }, { "CH Headers", "*.ch" } }
|
|
cFile := oDlg:open( cDftPath, , .f. )
|
|
IF !empty( cFile )
|
|
::oIde:cLastFileOpenPath := cFile
|
|
ENDIF
|
|
|
|
ELSEIF cMode == "openmany"
|
|
oDlg:title := "Select Sources"
|
|
oDlg:center := .t.
|
|
oDlg:defExtension:= 'prg'
|
|
oDlg:fileFilters := { { "All Files" , "*.*" }, { "PRG Sources", "*.prg" }, { "C Sources" , "*.c" },;
|
|
{ "CPP Sources", "*.cpp" }, { "H Headers" , "*.h" }, { "CH Headers", "*.ch" } }
|
|
cFile := oDlg:open( cDftPath, , .t. )
|
|
IF !empty( cFile ) .AND. !empty( cFile[ 1 ] )
|
|
::oIde:cLastFileOpenPath := cFile[ 1 ]
|
|
ENDIF
|
|
|
|
ELSEIF cMode == "save"
|
|
oDlg:title := iif( !hb_isChar( cTitle ), "Save as...", cTitle )
|
|
oDlg:center := .t.
|
|
oDlg:defExtension:= 'prg'
|
|
|
|
IF hb_isChar( cFile ) .AND. !Empty( cFile )
|
|
IF Right( cFile, 1 ) $ '/\'
|
|
cPath := cFile
|
|
ELSE
|
|
hb_fNameSplit( cFile, @cPath )
|
|
Endif
|
|
Endif
|
|
|
|
oDlg:fileFilters := { { "PRG Sources", "*.prg" }, { "C Sources", "*.c" }, { "CPP Sources", "*.cpp" }, ;
|
|
{ "H Headers", "*.h" }, { "CH Headers", "*.ch" } }
|
|
cFile := oDlg:saveAs( cPath )
|
|
|
|
ELSE
|
|
oDlg:title := "Save this Database"
|
|
oDlg:fileFilters := { { "Database Files", "*.dbf" } }
|
|
oDlg:quit := {|| MsgBox( "Quitting the Dialog" ), 1 }
|
|
cFile := oDlg:saveAs( "myfile.dbf" )
|
|
IF !empty( cFile )
|
|
HB_TRACE( HB_TR_DEBUG, cFile )
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN cFile
|
|
|
|
/*----------------------------------------------------------------------*/
|