mirror of https://github.com/python/cpython
Drop Mac wrappers for the WASTE library.
This commit is contained in:
parent
f70b14fb30
commit
fb2a169ce3
|
@ -95,14 +95,3 @@ audio tracks.
|
|||
|
||||
The \module{W} widgets are used extensively in the \program{IDE}.
|
||||
|
||||
\section{\module{waste} --- non-Apple \program{TextEdit} replacement}
|
||||
\declaremodule{standard}{waste}
|
||||
\platform{Mac}
|
||||
\modulesynopsis{Interface to the ``WorldScript-Aware Styled Text Engine.''}
|
||||
|
||||
\begin{seealso}
|
||||
\seetitle[http://www.merzwaren.com/waste/]{About WASTE}{Information
|
||||
about the WASTE widget and library, including
|
||||
documentation and downloads.}
|
||||
\end{seealso}
|
||||
|
||||
|
|
|
@ -1,207 +0,0 @@
|
|||
# Generated from 'WASTE.h'
|
||||
|
||||
kPascalStackBased = None # workaround for header parsing
|
||||
def FOUR_CHAR_CODE(x): return x
|
||||
weCantUndoErr = -10015
|
||||
weEmptySelectionErr = -10013
|
||||
weUnknownObjectTypeErr = -9478
|
||||
weObjectNotFoundErr = -9477
|
||||
weReadOnlyErr = -9476
|
||||
weTextNotFoundErr = -9474
|
||||
weInvalidTextEncodingErr = -9473
|
||||
weDuplicateAttributeErr = -9472
|
||||
weInvalidAttributeSizeErr = -9471
|
||||
weReadOnlyAttributeErr = -9470
|
||||
weOddByteCountErr = -9469
|
||||
weHandlerNotFoundErr = -1717
|
||||
weNotHandledErr = -1708
|
||||
weNewerVersionErr = -1706
|
||||
weCorruptDataErr = -1702
|
||||
weProtocolErr = -603
|
||||
weUndefinedSelectorErr = -50
|
||||
weFlushLeft = -2
|
||||
weFlushRight = -1
|
||||
weFlushDefault = 0
|
||||
weCenter = 1
|
||||
weJustify = 2
|
||||
weDirDefault = 1
|
||||
weDirRightToLeft = -1
|
||||
weDirLeftToRight = 0
|
||||
weDoFont = 0x0001
|
||||
weDoFace = 0x0002
|
||||
weDoSize = 0x0004
|
||||
weDoColor = 0x0008
|
||||
weDoAll = weDoFont | weDoFace | weDoSize | weDoColor
|
||||
weDoAddSize = 0x0010
|
||||
weDoToggleFace = 0x0020
|
||||
weDoReplaceFace = 0x0040
|
||||
weDoPreserveScript = 0x0080
|
||||
weDoExtractSubscript = 0x0100
|
||||
weDoFaceMask = 0x0200
|
||||
weDoDirection = 0x00000001
|
||||
weDoAlignment = 0x00000002
|
||||
weDoLeftIndent = 0x00000004
|
||||
weDoRightIndent = 0x00000008
|
||||
weDoFirstLineIndent = 0x00000010
|
||||
weDoLineSpacing = 0x00000020
|
||||
weDoSpaceBefore = 0x00000040
|
||||
weDoSpaceAfter = 0x00000080
|
||||
weDoBottomBorderStyle = 0x00000400
|
||||
kLeadingEdge = -1
|
||||
kTrailingEdge = 0
|
||||
kObjectEdge = 2
|
||||
weFAutoScroll = 0
|
||||
weFOutlineHilite = 2
|
||||
weFReadOnly = 5
|
||||
weFUndo = 6
|
||||
weFIntCutAndPaste = 7
|
||||
weFDragAndDrop = 8
|
||||
weFInhibitRecal = 9
|
||||
weFUseTempMem = 10
|
||||
weFDrawOffscreen = 11
|
||||
weFInhibitRedraw = 12
|
||||
weFMonoStyled = 13
|
||||
weFMultipleUndo = 14
|
||||
weFNoKeyboardSync = 29
|
||||
weFInhibitICSupport = 30
|
||||
weFInhibitColor = 31
|
||||
# weDoAutoScroll = 1UL << weFAutoScroll
|
||||
# weDoOutlineHilite = 1UL << weFOutlineHilite
|
||||
# weDoReadOnly = 1UL << weFReadOnly
|
||||
# weDoUndo = 1UL << weFUndo
|
||||
# weDoIntCutAndPaste = 1UL << weFIntCutAndPaste
|
||||
# weDoDragAndDrop = 1UL << weFDragAndDrop
|
||||
# weDoInhibitRecal = 1UL << weFInhibitRecal
|
||||
# weDoUseTempMem = 1UL << weFUseTempMem
|
||||
# weDoDrawOffscreen = 1UL << weFDrawOffscreen
|
||||
# weDoInhibitRedraw = 1UL << weFInhibitRedraw
|
||||
# weDoMonoStyled = 1UL << weFMonoStyled
|
||||
# weDoMultipleUndo = 1UL << weFMultipleUndo
|
||||
# weDoNoKeyboardSync = 1UL << weFNoKeyboardSync
|
||||
# weDoInhibitICSupport = 1UL << weFInhibitICSupport
|
||||
# weDoInhibitColor = 1UL << weFInhibitColor
|
||||
weBitToggle = -2
|
||||
weBitTest = -1
|
||||
weBitClear = 0
|
||||
weBitSet = 1
|
||||
weLowerCase = 0
|
||||
weUpperCase = 1
|
||||
weFindWholeWords = 0x00000001
|
||||
weFindCaseInsensitive = 0x00000002
|
||||
weFindDiacriticalInsensitive = 0x00000004
|
||||
wePutIntCutAndPaste = 0x00000001
|
||||
wePutAddToTypingSequence = 0x00000002
|
||||
wePutDetectUnicodeBOM = 0x00000200
|
||||
weStreamDestinationKindMask = 0x000000FF
|
||||
weStreamIncludeObjects = 0x00000100
|
||||
weGetAddUnicodeBOM = 0x00000200
|
||||
weGetLittleEndian = 0x00000400
|
||||
weTagFontFamily = FOUR_CHAR_CODE('font')
|
||||
weTagFontSize = FOUR_CHAR_CODE('ptsz')
|
||||
weTagPlain = FOUR_CHAR_CODE('plan')
|
||||
weTagBold = FOUR_CHAR_CODE('bold')
|
||||
weTagItalic = FOUR_CHAR_CODE('ital')
|
||||
weTagUnderline = FOUR_CHAR_CODE('undl')
|
||||
weTagOutline = FOUR_CHAR_CODE('outl')
|
||||
weTagShadow = FOUR_CHAR_CODE('shad')
|
||||
weTagCondensed = FOUR_CHAR_CODE('cond')
|
||||
weTagExtended = FOUR_CHAR_CODE('pexp')
|
||||
weTagStrikethrough = FOUR_CHAR_CODE('strk')
|
||||
weTagTextColor = FOUR_CHAR_CODE('colr')
|
||||
weTagBackgroundColor = FOUR_CHAR_CODE('pbcl')
|
||||
weTagTransferMode = FOUR_CHAR_CODE('pptm')
|
||||
weTagVerticalShift = FOUR_CHAR_CODE('xshf')
|
||||
weTagAlignment = FOUR_CHAR_CODE('pjst')
|
||||
weTagDirection = FOUR_CHAR_CODE('LDIR')
|
||||
weTagLineSpacing = FOUR_CHAR_CODE('ledg')
|
||||
weTagLeftIndent = FOUR_CHAR_CODE('lein')
|
||||
weTagRightIndent = FOUR_CHAR_CODE('riin')
|
||||
weTagFirstLineIndent = FOUR_CHAR_CODE('fidt')
|
||||
weTagSpaceBefore = FOUR_CHAR_CODE('spbe')
|
||||
weTagSpaceAfter = FOUR_CHAR_CODE('spaf')
|
||||
weTagBottomBorderStyle = FOUR_CHAR_CODE('BBRD')
|
||||
weTagForceFontFamily = FOUR_CHAR_CODE('ffnt')
|
||||
weTagAddFontSize = FOUR_CHAR_CODE('+siz')
|
||||
weTagAddVerticalShift = FOUR_CHAR_CODE('+shf')
|
||||
weTagTextEncoding = FOUR_CHAR_CODE('ptxe')
|
||||
weTagQDStyles = FOUR_CHAR_CODE('qdst')
|
||||
weTagTETextStyle = FOUR_CHAR_CODE('tets')
|
||||
weTagAlignmentDefault = FOUR_CHAR_CODE('deft')
|
||||
weTagAlignmentLeft = FOUR_CHAR_CODE('left')
|
||||
weTagAlignmentCenter = FOUR_CHAR_CODE('cent')
|
||||
weTagAlignmentRight = FOUR_CHAR_CODE('rght')
|
||||
weTagAlignmentFull = FOUR_CHAR_CODE('full')
|
||||
weTagDirectionDefault = FOUR_CHAR_CODE('deft')
|
||||
weTagDirectionLeftToRight = FOUR_CHAR_CODE('L->R')
|
||||
weTagDirectionRightToLeft = FOUR_CHAR_CODE('R->L')
|
||||
weTagBorderStyleNone = FOUR_CHAR_CODE('NONE')
|
||||
weTagBorderStyleThin = FOUR_CHAR_CODE('SLDL')
|
||||
weTagBorderStyleDotted = FOUR_CHAR_CODE('DTDL')
|
||||
weTagBorderStyleThick = FOUR_CHAR_CODE('THKL')
|
||||
weLineSpacingSingle = 0x00000000
|
||||
weLineSpacingOneAndHalf = 0x00008000
|
||||
weLineSpacingDouble = 0x00010000
|
||||
weCharByteHook = FOUR_CHAR_CODE('cbyt')
|
||||
weCharToPixelHook = FOUR_CHAR_CODE('c2p ')
|
||||
weCharTypeHook = FOUR_CHAR_CODE('ctyp')
|
||||
weClickLoop = FOUR_CHAR_CODE('clik')
|
||||
weCurrentDrag = FOUR_CHAR_CODE('drag')
|
||||
weDrawTextHook = FOUR_CHAR_CODE('draw')
|
||||
weDrawTSMHiliteHook = FOUR_CHAR_CODE('dtsm')
|
||||
weEraseHook = FOUR_CHAR_CODE('eras')
|
||||
weFontFamilyToNameHook = FOUR_CHAR_CODE('ff2n')
|
||||
weFontNameToFamilyHook = FOUR_CHAR_CODE('fn2f')
|
||||
weFluxProc = FOUR_CHAR_CODE('flux')
|
||||
weHiliteDropAreaHook = FOUR_CHAR_CODE('hidr')
|
||||
weLineBreakHook = FOUR_CHAR_CODE('lbrk')
|
||||
wePixelToCharHook = FOUR_CHAR_CODE('p2c ')
|
||||
wePort = FOUR_CHAR_CODE('port')
|
||||
wePreTrackDragHook = FOUR_CHAR_CODE('ptrk')
|
||||
weRefCon = FOUR_CHAR_CODE('refc')
|
||||
weScrollProc = FOUR_CHAR_CODE('scrl')
|
||||
weText = FOUR_CHAR_CODE('text')
|
||||
weTranslateDragHook = FOUR_CHAR_CODE('xdrg')
|
||||
weTranslucencyThreshold = FOUR_CHAR_CODE('tluc')
|
||||
weTSMDocumentID = FOUR_CHAR_CODE('tsmd')
|
||||
weTSMPreUpdate = FOUR_CHAR_CODE('pre ')
|
||||
weTSMPostUpdate = FOUR_CHAR_CODE('post')
|
||||
weURLHint = FOUR_CHAR_CODE('urlh')
|
||||
weWordBreakHook = FOUR_CHAR_CODE('wbrk')
|
||||
weNewHandler = FOUR_CHAR_CODE('new ')
|
||||
weDisposeHandler = FOUR_CHAR_CODE('free')
|
||||
weDrawHandler = FOUR_CHAR_CODE('draw')
|
||||
weClickHandler = FOUR_CHAR_CODE('clik')
|
||||
weStreamHandler = FOUR_CHAR_CODE('strm')
|
||||
weHoverHandler = FOUR_CHAR_CODE('hovr')
|
||||
kTypeText = FOUR_CHAR_CODE('TEXT')
|
||||
kTypeStyles = FOUR_CHAR_CODE('styl')
|
||||
kTypeSoup = FOUR_CHAR_CODE('SOUP')
|
||||
kTypeFontTable = FOUR_CHAR_CODE('FISH')
|
||||
kTypeParaFormat = FOUR_CHAR_CODE('WEpf')
|
||||
kTypeRulerScrap = FOUR_CHAR_CODE('WEru')
|
||||
kTypeCharFormat = FOUR_CHAR_CODE('WEcf')
|
||||
kTypeStyleScrap = FOUR_CHAR_CODE('WEst')
|
||||
kTypeUnicodeText = FOUR_CHAR_CODE('utxt')
|
||||
kTypeUTF8Text = FOUR_CHAR_CODE('UTF8')
|
||||
kTypeStyledText = FOUR_CHAR_CODE('STXT')
|
||||
weAKNone = 0
|
||||
weAKUnspecified = 1
|
||||
weAKTyping = 2
|
||||
weAKCut = 3
|
||||
weAKPaste = 4
|
||||
weAKClear = 5
|
||||
weAKDrag = 6
|
||||
weAKSetStyle = 7
|
||||
weAKSetRuler = 8
|
||||
weAKBackspace = 9
|
||||
weAKFwdDelete = 10
|
||||
weAKCaseChange = 11
|
||||
weAKObjectChange = 12
|
||||
weToScrap = 0
|
||||
weToDrag = 1
|
||||
weToSoup = 2
|
||||
weMouseEnter = 0
|
||||
weMouseWithin = 1
|
||||
weMouseLeave = 2
|
||||
kCurrentSelection = -1
|
||||
kNullStyle = -2
|
|
@ -1,207 +0,0 @@
|
|||
# Generated from 'WASTE.h'
|
||||
|
||||
kPascalStackBased = None # workaround for header parsing
|
||||
def FOUR_CHAR_CODE(x): return x
|
||||
weCantUndoErr = -10015
|
||||
weEmptySelectionErr = -10013
|
||||
weUnknownObjectTypeErr = -9478
|
||||
weObjectNotFoundErr = -9477
|
||||
weReadOnlyErr = -9476
|
||||
weTextNotFoundErr = -9474
|
||||
weInvalidTextEncodingErr = -9473
|
||||
weDuplicateAttributeErr = -9472
|
||||
weInvalidAttributeSizeErr = -9471
|
||||
weReadOnlyAttributeErr = -9470
|
||||
weOddByteCountErr = -9469
|
||||
weHandlerNotFoundErr = -1717
|
||||
weNotHandledErr = -1708
|
||||
weNewerVersionErr = -1706
|
||||
weCorruptDataErr = -1702
|
||||
weProtocolErr = -603
|
||||
weUndefinedSelectorErr = -50
|
||||
weFlushLeft = -2
|
||||
weFlushRight = -1
|
||||
weFlushDefault = 0
|
||||
weCenter = 1
|
||||
weJustify = 2
|
||||
weDirDefault = 1
|
||||
weDirRightToLeft = -1
|
||||
weDirLeftToRight = 0
|
||||
weDoFont = 0x0001
|
||||
weDoFace = 0x0002
|
||||
weDoSize = 0x0004
|
||||
weDoColor = 0x0008
|
||||
weDoAll = weDoFont | weDoFace | weDoSize | weDoColor
|
||||
weDoAddSize = 0x0010
|
||||
weDoToggleFace = 0x0020
|
||||
weDoReplaceFace = 0x0040
|
||||
weDoPreserveScript = 0x0080
|
||||
weDoExtractSubscript = 0x0100
|
||||
weDoFaceMask = 0x0200
|
||||
weDoDirection = 0x00000001
|
||||
weDoAlignment = 0x00000002
|
||||
weDoLeftIndent = 0x00000004
|
||||
weDoRightIndent = 0x00000008
|
||||
weDoFirstLineIndent = 0x00000010
|
||||
weDoLineSpacing = 0x00000020
|
||||
weDoSpaceBefore = 0x00000040
|
||||
weDoSpaceAfter = 0x00000080
|
||||
weDoBottomBorderStyle = 0x00000400
|
||||
kLeadingEdge = -1
|
||||
kTrailingEdge = 0
|
||||
kObjectEdge = 2
|
||||
weFAutoScroll = 0
|
||||
weFOutlineHilite = 2
|
||||
weFReadOnly = 5
|
||||
weFUndo = 6
|
||||
weFIntCutAndPaste = 7
|
||||
weFDragAndDrop = 8
|
||||
weFInhibitRecal = 9
|
||||
weFUseTempMem = 10
|
||||
weFDrawOffscreen = 11
|
||||
weFInhibitRedraw = 12
|
||||
weFMonoStyled = 13
|
||||
weFMultipleUndo = 14
|
||||
weFNoKeyboardSync = 29
|
||||
weFInhibitICSupport = 30
|
||||
weFInhibitColor = 31
|
||||
weDoAutoScroll = 1 << weFAutoScroll
|
||||
weDoOutlineHilite = 1 << weFOutlineHilite
|
||||
weDoReadOnly = 1 << weFReadOnly
|
||||
weDoUndo = 1 << weFUndo
|
||||
weDoIntCutAndPaste = 1 << weFIntCutAndPaste
|
||||
weDoDragAndDrop = 1 << weFDragAndDrop
|
||||
weDoInhibitRecal = 1 << weFInhibitRecal
|
||||
weDoUseTempMem = 1 << weFUseTempMem
|
||||
weDoDrawOffscreen = 1 << weFDrawOffscreen
|
||||
weDoInhibitRedraw = 1 << weFInhibitRedraw
|
||||
weDoMonoStyled = 1 << weFMonoStyled
|
||||
weDoMultipleUndo = 1 << weFMultipleUndo
|
||||
weDoNoKeyboardSync = 1 << weFNoKeyboardSync
|
||||
weDoInhibitICSupport = 1 << weFInhibitICSupport
|
||||
# weDoInhibitColor = 1 << weFInhibitColor
|
||||
weBitToggle = -2
|
||||
weBitTest = -1
|
||||
weBitClear = 0
|
||||
weBitSet = 1
|
||||
weLowerCase = 0
|
||||
weUpperCase = 1
|
||||
weFindWholeWords = 0x00000001
|
||||
weFindCaseInsensitive = 0x00000002
|
||||
weFindDiacriticalInsensitive = 0x00000004
|
||||
wePutIntCutAndPaste = 0x00000001
|
||||
wePutAddToTypingSequence = 0x00000002
|
||||
wePutDetectUnicodeBOM = 0x00000200
|
||||
weStreamDestinationKindMask = 0x000000FF
|
||||
weStreamIncludeObjects = 0x00000100
|
||||
weGetAddUnicodeBOM = 0x00000200
|
||||
weGetLittleEndian = 0x00000400
|
||||
weTagFontFamily = FOUR_CHAR_CODE('font')
|
||||
weTagFontSize = FOUR_CHAR_CODE('ptsz')
|
||||
weTagPlain = FOUR_CHAR_CODE('plan')
|
||||
weTagBold = FOUR_CHAR_CODE('bold')
|
||||
weTagItalic = FOUR_CHAR_CODE('ital')
|
||||
weTagUnderline = FOUR_CHAR_CODE('undl')
|
||||
weTagOutline = FOUR_CHAR_CODE('outl')
|
||||
weTagShadow = FOUR_CHAR_CODE('shad')
|
||||
weTagCondensed = FOUR_CHAR_CODE('cond')
|
||||
weTagExtended = FOUR_CHAR_CODE('pexp')
|
||||
weTagStrikethrough = FOUR_CHAR_CODE('strk')
|
||||
weTagTextColor = FOUR_CHAR_CODE('colr')
|
||||
weTagBackgroundColor = FOUR_CHAR_CODE('pbcl')
|
||||
weTagTransferMode = FOUR_CHAR_CODE('pptm')
|
||||
weTagVerticalShift = FOUR_CHAR_CODE('xshf')
|
||||
weTagAlignment = FOUR_CHAR_CODE('pjst')
|
||||
weTagDirection = FOUR_CHAR_CODE('LDIR')
|
||||
weTagLineSpacing = FOUR_CHAR_CODE('ledg')
|
||||
weTagLeftIndent = FOUR_CHAR_CODE('lein')
|
||||
weTagRightIndent = FOUR_CHAR_CODE('riin')
|
||||
weTagFirstLineIndent = FOUR_CHAR_CODE('fidt')
|
||||
weTagSpaceBefore = FOUR_CHAR_CODE('spbe')
|
||||
weTagSpaceAfter = FOUR_CHAR_CODE('spaf')
|
||||
weTagBottomBorderStyle = FOUR_CHAR_CODE('BBRD')
|
||||
weTagForceFontFamily = FOUR_CHAR_CODE('ffnt')
|
||||
weTagAddFontSize = FOUR_CHAR_CODE('+siz')
|
||||
weTagAddVerticalShift = FOUR_CHAR_CODE('+shf')
|
||||
weTagTextEncoding = FOUR_CHAR_CODE('ptxe')
|
||||
weTagQDStyles = FOUR_CHAR_CODE('qdst')
|
||||
weTagTETextStyle = FOUR_CHAR_CODE('tets')
|
||||
weTagAlignmentDefault = FOUR_CHAR_CODE('deft')
|
||||
weTagAlignmentLeft = FOUR_CHAR_CODE('left')
|
||||
weTagAlignmentCenter = FOUR_CHAR_CODE('cent')
|
||||
weTagAlignmentRight = FOUR_CHAR_CODE('rght')
|
||||
weTagAlignmentFull = FOUR_CHAR_CODE('full')
|
||||
weTagDirectionDefault = FOUR_CHAR_CODE('deft')
|
||||
weTagDirectionLeftToRight = FOUR_CHAR_CODE('L->R')
|
||||
weTagDirectionRightToLeft = FOUR_CHAR_CODE('R->L')
|
||||
weTagBorderStyleNone = FOUR_CHAR_CODE('NONE')
|
||||
weTagBorderStyleThin = FOUR_CHAR_CODE('SLDL')
|
||||
weTagBorderStyleDotted = FOUR_CHAR_CODE('DTDL')
|
||||
weTagBorderStyleThick = FOUR_CHAR_CODE('THKL')
|
||||
weLineSpacingSingle = 0x00000000
|
||||
weLineSpacingOneAndHalf = 0x00008000
|
||||
weLineSpacingDouble = 0x00010000
|
||||
weCharByteHook = FOUR_CHAR_CODE('cbyt')
|
||||
weCharToPixelHook = FOUR_CHAR_CODE('c2p ')
|
||||
weCharTypeHook = FOUR_CHAR_CODE('ctyp')
|
||||
weClickLoop = FOUR_CHAR_CODE('clik')
|
||||
weCurrentDrag = FOUR_CHAR_CODE('drag')
|
||||
weDrawTextHook = FOUR_CHAR_CODE('draw')
|
||||
weDrawTSMHiliteHook = FOUR_CHAR_CODE('dtsm')
|
||||
weEraseHook = FOUR_CHAR_CODE('eras')
|
||||
weFontFamilyToNameHook = FOUR_CHAR_CODE('ff2n')
|
||||
weFontNameToFamilyHook = FOUR_CHAR_CODE('fn2f')
|
||||
weFluxProc = FOUR_CHAR_CODE('flux')
|
||||
weHiliteDropAreaHook = FOUR_CHAR_CODE('hidr')
|
||||
weLineBreakHook = FOUR_CHAR_CODE('lbrk')
|
||||
wePixelToCharHook = FOUR_CHAR_CODE('p2c ')
|
||||
wePort = FOUR_CHAR_CODE('port')
|
||||
wePreTrackDragHook = FOUR_CHAR_CODE('ptrk')
|
||||
weRefCon = FOUR_CHAR_CODE('refc')
|
||||
weScrollProc = FOUR_CHAR_CODE('scrl')
|
||||
weText = FOUR_CHAR_CODE('text')
|
||||
weTranslateDragHook = FOUR_CHAR_CODE('xdrg')
|
||||
weTranslucencyThreshold = FOUR_CHAR_CODE('tluc')
|
||||
weTSMDocumentID = FOUR_CHAR_CODE('tsmd')
|
||||
weTSMPreUpdate = FOUR_CHAR_CODE('pre ')
|
||||
weTSMPostUpdate = FOUR_CHAR_CODE('post')
|
||||
weURLHint = FOUR_CHAR_CODE('urlh')
|
||||
weWordBreakHook = FOUR_CHAR_CODE('wbrk')
|
||||
weNewHandler = FOUR_CHAR_CODE('new ')
|
||||
weDisposeHandler = FOUR_CHAR_CODE('free')
|
||||
weDrawHandler = FOUR_CHAR_CODE('draw')
|
||||
weClickHandler = FOUR_CHAR_CODE('clik')
|
||||
weStreamHandler = FOUR_CHAR_CODE('strm')
|
||||
weHoverHandler = FOUR_CHAR_CODE('hovr')
|
||||
kTypeText = FOUR_CHAR_CODE('TEXT')
|
||||
kTypeStyles = FOUR_CHAR_CODE('styl')
|
||||
kTypeSoup = FOUR_CHAR_CODE('SOUP')
|
||||
kTypeFontTable = FOUR_CHAR_CODE('FISH')
|
||||
kTypeParaFormat = FOUR_CHAR_CODE('WEpf')
|
||||
kTypeRulerScrap = FOUR_CHAR_CODE('WEru')
|
||||
kTypeCharFormat = FOUR_CHAR_CODE('WEcf')
|
||||
kTypeStyleScrap = FOUR_CHAR_CODE('WEst')
|
||||
kTypeUnicodeText = FOUR_CHAR_CODE('utxt')
|
||||
kTypeUTF8Text = FOUR_CHAR_CODE('UTF8')
|
||||
kTypeStyledText = FOUR_CHAR_CODE('STXT')
|
||||
weAKNone = 0
|
||||
weAKUnspecified = 1
|
||||
weAKTyping = 2
|
||||
weAKCut = 3
|
||||
weAKPaste = 4
|
||||
weAKClear = 5
|
||||
weAKDrag = 6
|
||||
weAKSetStyle = 7
|
||||
weAKSetRuler = 8
|
||||
weAKBackspace = 9
|
||||
weAKFwdDelete = 10
|
||||
weAKCaseChange = 11
|
||||
weAKObjectChange = 12
|
||||
weToScrap = 0
|
||||
weToDrag = 1
|
||||
weToSoup = 2
|
||||
weMouseEnter = 0
|
||||
weMouseWithin = 1
|
||||
weMouseLeave = 2
|
||||
kCurrentSelection = -1
|
||||
kNullStyle = -2
|
|
@ -73,10 +73,6 @@ with MacPython.
|
|||
how to use <code>FrameWork</code> application framework and the
|
||||
<code>TextEdit</code> toolbox to build a text editor.
|
||||
|
||||
<LI>
|
||||
<A HREF="waste.html">Using WASTE</A> expands on this editor by using
|
||||
WASTE, an extended TextEdit replacement.
|
||||
|
||||
<LI>
|
||||
<A HREF="plugins.html">Creating a C extension module on the Macintosh</A>
|
||||
is meant for the hardcore programmer, and shows how to create an
|
||||
|
|
|
@ -80,8 +80,7 @@ A modeless dialog window initialized from a DLOG resource. See the
|
|||
|
||||
Let us have a look at <A HREF="textedit/ped.py">ped.py</A> (in the Demo:textedit folder), the Pathetic
|
||||
EDitor. It has multiple windows, cut/copy/paste and keyboard input, but that is about all. It looks
|
||||
as if you can resize the window but it does not work. Still, it serves as an example. We will improve
|
||||
on ped later, in a <A HREF="waste.html">waste-based example</A>. <p>
|
||||
as if you can resize the window but it does not work. Still, it serves as an example.
|
||||
|
||||
Ped creates two classes, <code>TEWindow</code> and <code>Ped</code>. Let us start with the latter one,
|
||||
which is a subclass of <code>FrameWork.Application</code> and our main application. The init function
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
<HTML><HEAD><TITLE>Using WASTE</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using WASTE</H1>
|
||||
<HR>
|
||||
|
||||
WASTE is an almost-compatible TextEdit replacement which overcomes
|
||||
some of the limitations of it (like the 32K limit) and provides some extensions
|
||||
(drag and drop, images, undo support). Moreover, it has a much cleaner interface
|
||||
and is therefore easier integrated in Python. <p>
|
||||
|
||||
WASTE is written by Marco Piovanelli, <A HREF="mailto:piovanel@kagi.com"><piovanel@kagi.com></A>,
|
||||
and copyrighted by him. You can always obtain the latest version (for use in C
|
||||
or Pascal programs) and the documentation from
|
||||
<A HREF="http://www.boingo.com/waste/"><http://www.boingo.com/waste/></A>.
|
||||
|
||||
We explain the useage of waste here by showing how to modify the TextEdit based
|
||||
<A HREF="textedit/ped.py">ped.py</A> of the
|
||||
<A HREF="textedit.html">previous example</A> into the waste-based <A HREF="waste/wed.py">wed.py</A>,
|
||||
so you should have both sources handy. <p>
|
||||
|
||||
Functionally, <code>wed.py</code> provides three new things: resizable windows, a horizontal
|
||||
scroll bar and undo. <p>
|
||||
|
||||
Let us look at the code, first at the application class <code>Wed</code>. The only real change is that
|
||||
we now handle <code>undo</code>. Aside from enabling it in the creation routine and the addition of
|
||||
a callback routine there is a bit of new code in <code>updatemenubar</code>: Waste not only handles
|
||||
the full details of implementing undo, it will also tell us what the next undo operation will undo
|
||||
(or redo). We use this to our advantage by changing the undo menu label to tell the user. <p>
|
||||
|
||||
The <code>WasteWindow</code> has seen a bit more change. Initialization of the waste data structure is
|
||||
a bit different, in that we can specify some options at creation time. Also, waste has no <code>SetText</code>
|
||||
method but a <code>UseText</code> which expects a handle as parameter. We have to be <EM>very</EM> careful
|
||||
that we keep this handle around, because Python will happily free the handle if we have no more references
|
||||
to it (and I doubt that Waste would like this:-). A final difference in <code>open</code>
|
||||
is that we use a large number for the destination rectangle width, because we will use a horizontal scroll
|
||||
bar. <p>
|
||||
|
||||
The <code>idle</code> method is a bit more involved, since we also call <code>WEAdjustCursor</code> to
|
||||
provide the correct cursor based on mouse-position. Users like this. <p>
|
||||
|
||||
<code>Getscrollbarvalues</code> is simpler than its' TextEdit counterpart because Waste correctly
|
||||
updates the destination rectangle when the document changes. Also note that waste uses accessor functions
|
||||
to get at internal values, as opposed to direct struct access for TextEdit. <p>
|
||||
|
||||
<code>Scrollbar_callback</code> on the other hand is more elaborate (but also provides more functionality).
|
||||
It also handles horizontal scrolls (scrolling one-tenth and half a screenful with the buttons). This
|
||||
function is also "multi-font-ready" in that scrolling one line will do the expected thing in case of multiple
|
||||
fonts. We will implement a multi-font editor later. A minor annoyance of Waste is that is does not provide
|
||||
a pinned scroll, so at the end of our callback routine we have to check that we have not scrolled past the
|
||||
beginning or end of the document, and adjust when needed. <p>
|
||||
|
||||
<code>do_update</code> is also changed, because Waste is completely region-based (as opposed to rect-based).
|
||||
Hence, we erase regions here and we can also return immedeately if there is nothing to update. <p>
|
||||
|
||||
<code>Do_postresize</code> is new: because Waste uses accessor functions we can now modify the viewRect from
|
||||
Python, which is impossible in the Python TextEdit interface, and hence we can implement resize. The
|
||||
<code>do_key</code> and <code>do_contentclick</code> methods have also seen minor changes, because the
|
||||
corresponding waste routines need a bit more information than their TextEdit counterparts. The Cut/copy/paste
|
||||
code is simplified, because Waste uses the normal desktop scrap. <p>
|
||||
|
||||
Implementing undo is a wonder of simplicity: Waste handles all the details for us. Also, the new
|
||||
<code>can_paste</code> method (which controls greying out of the paste menu entry) is an improvement
|
||||
over what <code>ped</code> did: in ped it was possible that paste was enabled but that the data on the
|
||||
scrap was incompatible with TextEdit. No more such problems here. <p>
|
||||
|
||||
That is all for now. There is an undocumented extended version of wed, <a href="waste/swed.py">swed.py</a>,
|
||||
which supports multiple fonts, sizes and faces, and uses Waste's tab-calculation to do tab characters "right".
|
||||
There is also an even more elaborate example, <a href="waste/htmled.py">htmled.py</a> which extends swed with
|
||||
the ability to import html files, showing the use of color and how to use embedded object (rulers, in this case).
|
||||
These two programs have not been documented yet, though, so you will have to look at them without guidance. <p>
|
||||
<hr>
|
||||
Back to the <A HREF="index.html">index</A> to pick another example.
|
|
@ -1,830 +0,0 @@
|
|||
# A minimal text editor.
|
||||
#
|
||||
# To be done:
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Carbon.Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Qd
|
||||
from Carbon import Res
|
||||
from Carbon import Fm
|
||||
import waste
|
||||
import WASTEconst
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
import EasyDialogs
|
||||
import macfs
|
||||
import string
|
||||
import htmllib
|
||||
|
||||
WATCH = Qd.GetCursor(4).data
|
||||
|
||||
LEFTMARGIN=0
|
||||
|
||||
UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
|
||||
None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
|
||||
|
||||
# Style and size menu. Note that style order is important (tied to bit values)
|
||||
STYLES = [
|
||||
("Bold", "B"), ("Italic", "I"), ("Underline", "U"), ("Outline", "O"),
|
||||
("Shadow", ""), ("Condensed", ""), ("Extended", "")
|
||||
]
|
||||
SIZES = [ 9, 10, 12, 14, 18, 24]
|
||||
|
||||
# Sizes for HTML tag types
|
||||
HTML_SIZE={
|
||||
'h1': 18,
|
||||
'h2': 14
|
||||
}
|
||||
|
||||
BIGREGION=Qd.NewRgn()
|
||||
Qd.SetRectRgn(BIGREGION, -16000, -16000, 16000, 16000)
|
||||
|
||||
class WasteWindow(ScrolledWindow):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
vr = LEFTMARGIN, 0, r[2]-r[0]-15, r[3]-r[1]-15
|
||||
dr = (0, 0, vr[2], 0)
|
||||
Qd.SetPort(w)
|
||||
Qd.TextFont(4)
|
||||
Qd.TextSize(9)
|
||||
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite | \
|
||||
WASTEconst.weDoMonoStyled | WASTEconst.weDoUndo
|
||||
self.ted = waste.WENew(dr, vr, flags)
|
||||
self.ted.WEInstallTabHooks()
|
||||
style, soup = self.getstylesoup(self.path)
|
||||
self.ted.WEInsert(data, style, soup)
|
||||
self.ted.WESetSelection(0,0)
|
||||
self.ted.WECalText()
|
||||
self.ted.WEResetModCount()
|
||||
w.DrawGrowIcon()
|
||||
self.scrollbars()
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def getstylesoup(self, pathname):
|
||||
if not pathname:
|
||||
return None, None
|
||||
oldrf = Res.CurResFile()
|
||||
try:
|
||||
rf = Res.FSpOpenResFile(self.path, 1)
|
||||
except Res.Error:
|
||||
return None, None
|
||||
try:
|
||||
hstyle = Res.Get1Resource('styl', 128)
|
||||
hstyle.DetachResource()
|
||||
except Res.Error:
|
||||
hstyle = None
|
||||
try:
|
||||
hsoup = Res.Get1Resource('SOUP', 128)
|
||||
hsoup.DetachResource()
|
||||
except Res.Error:
|
||||
hsoup = None
|
||||
Res.CloseResFile(rf)
|
||||
Res.UseResFile(oldrf)
|
||||
return hstyle, hsoup
|
||||
|
||||
def do_idle(self, event):
|
||||
(what, message, when, where, modifiers) = event
|
||||
Qd.SetPort(self.wid)
|
||||
self.ted.WEIdle()
|
||||
if self.ted.WEAdjustCursor(where, BIGREGION):
|
||||
return
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def getscrollbarvalues(self):
|
||||
dr = self.ted.WEGetDestRect()
|
||||
vr = self.ted.WEGetViewRect()
|
||||
vx = self.scalebarvalue(dr[0], dr[2], vr[0], vr[2])
|
||||
vy = self.scalebarvalue(dr[1], dr[3], vr[1], vr[3])
|
||||
return vx, vy
|
||||
|
||||
def scrollbar_callback(self, which, what, value):
|
||||
if which == 'y':
|
||||
#
|
||||
# "line" size is minimum of top and bottom line size
|
||||
#
|
||||
topline_off,dummy = self.ted.WEGetOffset((1,1))
|
||||
topline_num = self.ted.WEOffsetToLine(topline_off)
|
||||
toplineheight = self.ted.WEGetHeight(topline_num, topline_num+1)
|
||||
|
||||
botlinepos = self.ted.WEGetViewRect()[3]
|
||||
botline_off, dummy = self.ted.WEGetOffset((1, botlinepos-1))
|
||||
botline_num = self.ted.WEOffsetToLine(botline_off)
|
||||
botlineheight = self.ted.WEGetHeight(botline_num, botline_num+1)
|
||||
|
||||
if botlineheight == 0:
|
||||
botlineheight = self.ted.WEGetHeight(botline_num-1, botline_num)
|
||||
if botlineheight < toplineheight:
|
||||
lineheight = botlineheight
|
||||
else:
|
||||
lineheight = toplineheight
|
||||
if lineheight <= 0:
|
||||
lineheight = 1
|
||||
#
|
||||
# Now do the command.
|
||||
#
|
||||
if what == 'set':
|
||||
height = self.ted.WEGetHeight(0, 0x3fffffff)
|
||||
cur = self.getscrollbarvalues()[1]
|
||||
delta = (cur-value)*height/32767
|
||||
if what == '-':
|
||||
delta = lineheight
|
||||
elif what == '--':
|
||||
delta = (self.ted.WEGetViewRect()[3]-lineheight)
|
||||
if delta <= 0:
|
||||
delta = lineheight
|
||||
elif what == '+':
|
||||
delta = -lineheight
|
||||
elif what == '++':
|
||||
delta = -(self.ted.WEGetViewRect()[3]-lineheight)
|
||||
if delta >= 0:
|
||||
delta = -lineheight
|
||||
self.ted.WEScroll(0, delta)
|
||||
else:
|
||||
if what == 'set':
|
||||
return # XXXX
|
||||
vr = self.ted.WEGetViewRect()
|
||||
winwidth = vr[2]-vr[0]
|
||||
if what == '-':
|
||||
delta = winwidth/10
|
||||
elif what == '--':
|
||||
delta = winwidth/2
|
||||
elif what == '+':
|
||||
delta = -winwidth/10
|
||||
elif what == '++':
|
||||
delta = -winwidth/2
|
||||
self.ted.WEScroll(delta, 0)
|
||||
# Pin the scroll
|
||||
l, t, r, b = self.ted.WEGetDestRect()
|
||||
vl, vt, vr, vb = self.ted.WEGetViewRect()
|
||||
if t > 0 or l > 0:
|
||||
dx = dy = 0
|
||||
if t > 0: dy = -t
|
||||
if l > 0: dx = -l
|
||||
self.ted.WEScroll(dx, dy)
|
||||
elif b < vb:
|
||||
self.ted.WEScroll(0, vb-b)
|
||||
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
Qd.SetPort(self.wid)
|
||||
ScrolledWindow.do_activate(self, onoff, evt)
|
||||
if onoff:
|
||||
self.ted.WEActivate()
|
||||
self.parent.active = self
|
||||
self.parent.updatemenubar()
|
||||
else:
|
||||
self.ted.WEDeactivate()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
region = wid.GetWindowPort().visRgn
|
||||
if Qd.EmptyRgn(region):
|
||||
return
|
||||
Qd.EraseRgn(region)
|
||||
self.ted.WEUpdate(region)
|
||||
self.updatescrollbars()
|
||||
|
||||
def do_postresize(self, width, height, window):
|
||||
l, t, r, b = self.ted.WEGetViewRect()
|
||||
vr = (l, t, l+width-15, t+height-15)
|
||||
self.ted.WESetViewRect(vr)
|
||||
self.wid.InvalWindowRect(vr)
|
||||
ScrolledWindow.do_postresize(self, width, height, window)
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
(what, message, when, where, modifiers) = evt
|
||||
self.ted.WEClick(local, modifiers, when)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.WESelView()
|
||||
(what, message, when, where, modifiers) = event
|
||||
self.ted.WEKey(ord(ch), modifiers)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.ted.WEGetModCount():
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
del self.ted
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
#
|
||||
# First save data
|
||||
#
|
||||
dhandle = self.ted.WEGetText()
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
#
|
||||
# Now save style and soup
|
||||
#
|
||||
oldresfile = Res.CurResFile()
|
||||
try:
|
||||
rf = Res.FSpOpenResFile(self.path, 3)
|
||||
except Res.Error:
|
||||
Res.FSpCreateResFile(self.path, '????', 'TEXT', macfs.smAllScripts)
|
||||
rf = Res.FSpOpenResFile(self.path, 3)
|
||||
styles = Res.Resource('')
|
||||
soup = Res.Resource('')
|
||||
self.ted.WECopyRange(0, 0x3fffffff, None, styles, soup)
|
||||
styles.AddResource('styl', 128, '')
|
||||
soup.AddResource('SOUP', 128, '')
|
||||
Res.CloseResFile(rf)
|
||||
Res.UseResFile(oldresfile)
|
||||
|
||||
self.ted.WEResetModCount()
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_insert(self, fp):
|
||||
self.ted.WESelView()
|
||||
data = fp.read()
|
||||
self.ted.WEInsert(data, None, None)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_insert_html(self, fp):
|
||||
import htmllib
|
||||
import formatter
|
||||
f = formatter.AbstractFormatter(self)
|
||||
|
||||
# Remember where we are, and don't update
|
||||
Qd.SetCursor(WATCH)
|
||||
start, dummy = self.ted.WEGetSelection()
|
||||
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
|
||||
|
||||
self.html_init()
|
||||
p = MyHTMLParser(f)
|
||||
p.feed(fp.read())
|
||||
|
||||
# Restore updating, recalc, set focus
|
||||
dummy, end = self.ted.WEGetSelection()
|
||||
self.ted.WECalText()
|
||||
self.ted.WESetSelection(start, end)
|
||||
self.ted.WESelView()
|
||||
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
|
||||
self.wid.InvalWindowRect(self.ted.WEGetViewRect())
|
||||
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_cut(self):
|
||||
self.ted.WESelView()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECut()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_copy(self):
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECopy()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEPaste()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_clear(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEDelete()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_undo(self):
|
||||
self.ted.WEUndo()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_setfont(self, font):
|
||||
font = Fm.GetFNum(font)
|
||||
self.mysetstyle(WASTEconst.weDoFont, (font, 0, 0, (0,0,0)))
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_modface(self, face):
|
||||
self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoToggleFace,
|
||||
(0, face, 0, (0,0,0)))
|
||||
|
||||
def menu_setface(self, face):
|
||||
self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoReplaceFace,
|
||||
(0, face, 0, (0,0,0)))
|
||||
|
||||
def menu_setsize(self, size):
|
||||
self.mysetstyle(WASTEconst.weDoSize, (0, 0, size, (0,0,0)))
|
||||
|
||||
def menu_incsize(self, size):
|
||||
self.mysetstyle(WASTEconst.weDoAddSize, (0, 0, size, (0,0,0)))
|
||||
|
||||
def mysetstyle(self, which, how):
|
||||
self.ted.WESelView()
|
||||
self.ted.WESetStyle(which, how)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def have_selection(self):
|
||||
start, stop = self.ted.WEGetSelection()
|
||||
return start < stop
|
||||
|
||||
def can_paste(self):
|
||||
return self.ted.WECanPaste()
|
||||
|
||||
def can_undo(self):
|
||||
which, redo = self.ted.WEGetUndoInfo()
|
||||
which = UNDOLABELS[which]
|
||||
if which == None: return None
|
||||
if redo:
|
||||
return "Redo "+which
|
||||
else:
|
||||
return "Undo "+which
|
||||
|
||||
def getruninfo(self):
|
||||
all = (WASTEconst.weDoFont | WASTEconst.weDoFace | WASTEconst.weDoSize)
|
||||
dummy, mode, (font, face, size, color) = self.ted.WEContinuousStyle(all)
|
||||
if not (mode & WASTEconst.weDoFont):
|
||||
font = None
|
||||
else:
|
||||
font = Fm.GetFontName(font)
|
||||
if not (mode & WASTEconst.weDoFace): fact = None
|
||||
if not (mode & WASTEconst.weDoSize): size = None
|
||||
return font, face, size
|
||||
|
||||
#
|
||||
# Methods for writer class for html formatter
|
||||
#
|
||||
|
||||
def html_init(self):
|
||||
self.html_font = [12, 0, 0, 0]
|
||||
self.html_style = 0
|
||||
self.html_color = (0,0,0)
|
||||
self.new_font(self.html_font)
|
||||
|
||||
def new_font(self, font):
|
||||
if font == None:
|
||||
font = (12, 0, 0, 0)
|
||||
font = map(lambda x:x, font)
|
||||
for i in range(len(font)):
|
||||
if font[i] == None:
|
||||
font[i] = self.html_font[i]
|
||||
[size, italic, bold, tt] = font
|
||||
self.html_font = font[:]
|
||||
if tt:
|
||||
font = Fm.GetFNum('Courier')
|
||||
else:
|
||||
font = Fm.GetFNum('Times')
|
||||
if HTML_SIZE.has_key(size):
|
||||
size = HTML_SIZE[size]
|
||||
else:
|
||||
size = 12
|
||||
face = 0
|
||||
if bold: face = face | 1
|
||||
if italic: face = face | 2
|
||||
face = face | self.html_style
|
||||
self.ted.WESetStyle(WASTEconst.weDoFont | WASTEconst.weDoFace |
|
||||
WASTEconst.weDoSize | WASTEconst.weDoColor,
|
||||
(font, face, size, self.html_color))
|
||||
|
||||
def new_margin(self, margin, level):
|
||||
self.ted.WEInsert('[Margin %s %s]'%(margin, level), None, None)
|
||||
|
||||
def new_spacing(self, spacing):
|
||||
self.ted.WEInsert('[spacing %s]'%spacing, None, None)
|
||||
|
||||
def new_styles(self, styles):
|
||||
self.html_style = 0
|
||||
self.html_color = (0,0,0)
|
||||
if 'anchor' in styles:
|
||||
self.html_style = self.html_style | 4
|
||||
self.html_color = (0xffff, 0, 0)
|
||||
self.new_font(self.html_font)
|
||||
|
||||
def send_paragraph(self, blankline):
|
||||
self.ted.WEInsert('\r'*(blankline+1), None, None)
|
||||
|
||||
def send_line_break(self):
|
||||
self.ted.WEInsert('\r', None, None)
|
||||
|
||||
def send_hor_rule(self, *args, **kw):
|
||||
# Ignore ruler options, for now
|
||||
dummydata = Res.Resource('')
|
||||
self.ted.WEInsertObject('rulr', dummydata, (0,0))
|
||||
|
||||
def send_label_data(self, data):
|
||||
self.ted.WEInsert(data, None, None)
|
||||
|
||||
def send_flowing_data(self, data):
|
||||
self.ted.WEInsert(data, None, None)
|
||||
|
||||
def send_literal_data(self, data):
|
||||
data = string.replace(data, '\n', '\r')
|
||||
data = string.expandtabs(data)
|
||||
self.ted.WEInsert(data, None, None)
|
||||
|
||||
class Wed(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
waste.STDObjectHandlers()
|
||||
# Handler for horizontal ruler
|
||||
waste.WEInstallObjectHandler('rulr', 'new ', self.newRuler)
|
||||
waste.WEInstallObjectHandler('rulr', 'draw', self.drawRuler)
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.insertitem = MenuItem(m, "Insert plaintext...", "", self.insertfile)
|
||||
self.htmlitem = MenuItem(m, "Insert HTML...", "", self.inserthtml)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
self.makefontmenu()
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem,
|
||||
self.editmenu, self.fontmenu, self.facemenu, self.sizemenu,
|
||||
self.insertitem]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
self.undo_label = "never"
|
||||
self.ffs_values = ()
|
||||
|
||||
def makefontmenu(self):
|
||||
self.fontmenu = Menu(self.menubar, "Font")
|
||||
self.fontnames = getfontnames()
|
||||
self.fontitems = []
|
||||
for n in self.fontnames:
|
||||
m = MenuItem(self.fontmenu, n, "", self.selfont)
|
||||
self.fontitems.append(m)
|
||||
self.facemenu = Menu(self.menubar, "Style")
|
||||
self.faceitems = []
|
||||
for n, shortcut in STYLES:
|
||||
m = MenuItem(self.facemenu, n, shortcut, self.selface)
|
||||
self.faceitems.append(m)
|
||||
self.facemenu.addseparator()
|
||||
self.faceitem_normal = MenuItem(self.facemenu, "Normal", "N",
|
||||
self.selfacenormal)
|
||||
self.sizemenu = Menu(self.menubar, "Size")
|
||||
self.sizeitems = []
|
||||
for n in SIZES:
|
||||
m = MenuItem(self.sizemenu, repr(n), "", self.selsize)
|
||||
self.sizeitems.append(m)
|
||||
self.sizemenu.addseparator()
|
||||
self.sizeitem_bigger = MenuItem(self.sizemenu, "Bigger", "+",
|
||||
self.selsizebigger)
|
||||
self.sizeitem_smaller = MenuItem(self.sizemenu, "Smaller", "-",
|
||||
self.selsizesmaller)
|
||||
|
||||
def selfont(self, id, item, *rest):
|
||||
if self.active:
|
||||
font = self.fontnames[item-1]
|
||||
self.active.menu_setfont(font)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selface(self, id, item, *rest):
|
||||
if self.active:
|
||||
face = (1<<(item-1))
|
||||
self.active.menu_modface(face)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selfacenormal(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_setface(0)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsize(self, id, item, *rest):
|
||||
if self.active:
|
||||
size = SIZES[item-1]
|
||||
self.active.menu_setsize(size)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsizebigger(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_incsize(2)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsizesmaller(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_incsize(-2)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_paste()
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_undo()
|
||||
if on <> self.undo_label:
|
||||
if on:
|
||||
self.undoitem.enable(1)
|
||||
self.undoitem.settext(on)
|
||||
self.undo_label = on
|
||||
else:
|
||||
self.undoitem.settext("Nothing to undo")
|
||||
self.undoitem.enable(0)
|
||||
changed = 1
|
||||
if self.updatefontmenus():
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
def updatefontmenus(self):
|
||||
info = self.active.getruninfo()
|
||||
if info == self.ffs_values:
|
||||
return 0
|
||||
# Remove old checkmarks
|
||||
if self.ffs_values == ():
|
||||
self.ffs_values = (None, None, None)
|
||||
font, face, size = self.ffs_values
|
||||
if font <> None:
|
||||
fnum = self.fontnames.index(font)
|
||||
self.fontitems[fnum].check(0)
|
||||
if face <> None:
|
||||
for i in range(len(self.faceitems)):
|
||||
if face & (1<<i):
|
||||
self.faceitems[i].check(0)
|
||||
if size <> None:
|
||||
for i in range(len(self.sizeitems)):
|
||||
if SIZES[i] == size:
|
||||
self.sizeitems[i].check(0)
|
||||
|
||||
self.ffs_values = info
|
||||
# Set new checkmarks
|
||||
font, face, size = self.ffs_values
|
||||
if font <> None:
|
||||
fnum = self.fontnames.index(font)
|
||||
self.fontitems[fnum].check(1)
|
||||
if face <> None:
|
||||
for i in range(len(self.faceitems)):
|
||||
if face & (1<<i):
|
||||
self.faceitems[i].check(1)
|
||||
if size <> None:
|
||||
for i in range(len(self.sizeitems)):
|
||||
if SIZES[i] == size:
|
||||
self.sizeitems[i].check(1)
|
||||
# Set outline/normal for sizes
|
||||
if font:
|
||||
exists = getfontsizes(font, SIZES)
|
||||
for i in range(len(self.sizeitems)):
|
||||
if exists[i]:
|
||||
self.sizeitems[i].setstyle(0)
|
||||
else:
|
||||
self.sizeitems[i].setstyle(8)
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor based on WASTE")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = WasteWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def insertfile(self, *args):
|
||||
if self.active:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (args,))
|
||||
return
|
||||
self.active.menu_insert(fp)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def inserthtml(self, *args):
|
||||
if self.active:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
try:
|
||||
fp = open(path, 'r')
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
self.active.menu_insert_html(fp)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_undo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, event):
|
||||
if self.active:
|
||||
self.active.do_idle(event)
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def newRuler(self, obj):
|
||||
"""Insert a new ruler. Make it as wide as the window minus 2 pxls"""
|
||||
ted = obj.WEGetObjectOwner()
|
||||
l, t, r, b = ted.WEGetDestRect()
|
||||
return r-l, 4
|
||||
|
||||
def drawRuler(self, (l, t, r, b), obj):
|
||||
y = (t+b)/2
|
||||
Qd.MoveTo(l+2, y)
|
||||
Qd.LineTo(r-2, y)
|
||||
return 0
|
||||
|
||||
class MyHTMLParser(htmllib.HTMLParser):
|
||||
|
||||
def anchor_bgn(self, href, name, type):
|
||||
self.anchor = href
|
||||
if self.anchor:
|
||||
self.anchorlist.append(href)
|
||||
self.formatter.push_style('anchor')
|
||||
|
||||
def anchor_end(self):
|
||||
if self.anchor:
|
||||
self.anchor = None
|
||||
self.formatter.pop_style()
|
||||
|
||||
|
||||
def getfontnames():
|
||||
names = []
|
||||
for i in range(256):
|
||||
n = Fm.GetFontName(i)
|
||||
if n: names.append(n)
|
||||
return names
|
||||
|
||||
def getfontsizes(name, sizes):
|
||||
exist = []
|
||||
num = Fm.GetFNum(name)
|
||||
for sz in sizes:
|
||||
if Fm.RealFont(num, sz):
|
||||
exist.append(1)
|
||||
else:
|
||||
exist.append(0)
|
||||
return exist
|
||||
|
||||
def main():
|
||||
App = Wed()
|
||||
App.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,634 +0,0 @@
|
|||
# A minimal text editor.
|
||||
#
|
||||
# To be done:
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Carbon.Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Qd
|
||||
from Carbon import Res
|
||||
from Carbon import Fm
|
||||
import waste
|
||||
import WASTEconst
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
import macfs
|
||||
|
||||
UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
|
||||
None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
|
||||
|
||||
# Style and size menu. Note that style order is important (tied to bit values)
|
||||
STYLES = [
|
||||
("Bold", "B"), ("Italic", "I"), ("Underline", "U"), ("Outline", "O"),
|
||||
("Shadow", ""), ("Condensed", ""), ("Extended", "")
|
||||
]
|
||||
SIZES = [ 9, 10, 12, 14, 18, 24]
|
||||
|
||||
BIGREGION=Qd.NewRgn()
|
||||
Qd.SetRectRgn(BIGREGION, -16000, -16000, 16000, 16000)
|
||||
|
||||
class WasteWindow(ScrolledWindow):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
vr = 0, 0, r[2]-r[0]-15, r[3]-r[1]-15
|
||||
dr = (0, 0, 10240, 0)
|
||||
Qd.SetPort(w)
|
||||
Qd.TextFont(4)
|
||||
Qd.TextSize(9)
|
||||
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite | \
|
||||
WASTEconst.weDoUndo
|
||||
self.ted = waste.WENew(dr, vr, flags)
|
||||
self.ted.WEInstallTabHooks()
|
||||
style, soup = self.getstylesoup()
|
||||
self.ted.WEInsert(data, style, soup)
|
||||
self.ted.WESetSelection(0,0)
|
||||
self.ted.WECalText()
|
||||
self.ted.WEResetModCount()
|
||||
w.DrawGrowIcon()
|
||||
self.scrollbars()
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def getstylesoup(self):
|
||||
if not self.path:
|
||||
return None, None
|
||||
oldrf = Res.CurResFile()
|
||||
try:
|
||||
rf = Res.FSpOpenResFile(self.path, 1)
|
||||
except Res.Error:
|
||||
return None, None
|
||||
try:
|
||||
hstyle = Res.Get1Resource('styl', 128)
|
||||
hstyle.DetachResource()
|
||||
except Res.Error:
|
||||
hstyle = None
|
||||
try:
|
||||
hsoup = Res.Get1Resource('SOUP', 128)
|
||||
hsoup.DetachResource()
|
||||
except Res.Error:
|
||||
hsoup = None
|
||||
Res.CloseResFile(rf)
|
||||
Res.UseResFile(oldrf)
|
||||
return hstyle, hsoup
|
||||
|
||||
def do_idle(self, event):
|
||||
(what, message, when, where, modifiers) = event
|
||||
Qd.SetPort(self.wid)
|
||||
self.ted.WEIdle()
|
||||
if self.ted.WEAdjustCursor(where, BIGREGION):
|
||||
return
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def getscrollbarvalues(self):
|
||||
dr = self.ted.WEGetDestRect()
|
||||
vr = self.ted.WEGetViewRect()
|
||||
vx = self.scalebarvalue(dr[0], dr[2], vr[0], vr[2])
|
||||
vy = self.scalebarvalue(dr[1], dr[3], vr[1], vr[3])
|
||||
return vx, vy
|
||||
|
||||
def scrollbar_callback(self, which, what, value):
|
||||
if which == 'y':
|
||||
if what == 'set':
|
||||
height = self.ted.WEGetHeight(0, 0x3fffffff)
|
||||
cur = self.getscrollbarvalues()[1]
|
||||
delta = (cur-value)*height/32767
|
||||
if what == '-':
|
||||
topline_off,dummy = self.ted.WEGetOffset((1,1))
|
||||
topline_num = self.ted.WEOffsetToLine(topline_off)
|
||||
delta = self.ted.WEGetHeight(topline_num, topline_num+1)
|
||||
elif what == '--':
|
||||
delta = (self.ted.WEGetViewRect()[3]-10)
|
||||
if delta <= 0:
|
||||
delta = 10 # Random value
|
||||
elif what == '+':
|
||||
# XXXX Wrong: should be bottom line size
|
||||
topline_off,dummy = self.ted.WEGetOffset((1,1))
|
||||
topline_num = self.ted.WEOffsetToLine(topline_off)
|
||||
delta = -self.ted.WEGetHeight(topline_num, topline_num+1)
|
||||
elif what == '++':
|
||||
delta = -(self.ted.WEGetViewRect()[3]-10)
|
||||
if delta >= 0:
|
||||
delta = -10
|
||||
self.ted.WEScroll(0, delta)
|
||||
else:
|
||||
if what == 'set':
|
||||
return # XXXX
|
||||
vr = self.ted.WEGetViewRect()
|
||||
winwidth = vr[2]-vr[0]
|
||||
if what == '-':
|
||||
delta = winwidth/10
|
||||
elif what == '--':
|
||||
delta = winwidth/2
|
||||
elif what == '+':
|
||||
delta = -winwidth/10
|
||||
elif what == '++':
|
||||
delta = -winwidth/2
|
||||
self.ted.WEScroll(delta, 0)
|
||||
# Pin the scroll
|
||||
l, t, r, b = self.ted.WEGetDestRect()
|
||||
vl, vt, vr, vb = self.ted.WEGetViewRect()
|
||||
if t > 0 or l > 0:
|
||||
dx = dy = 0
|
||||
if t > 0: dy = -t
|
||||
if l > 0: dx = -l
|
||||
self.ted.WEScroll(dx, dy)
|
||||
elif b < vb:
|
||||
self.ted.WEScroll(0, b-vb)
|
||||
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
Qd.SetPort(self.wid)
|
||||
ScrolledWindow.do_activate(self, onoff, evt)
|
||||
if onoff:
|
||||
self.ted.WEActivate()
|
||||
self.parent.active = self
|
||||
self.parent.updatemenubar()
|
||||
else:
|
||||
self.ted.WEDeactivate()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
region = wid.GetWindowPort().visRgn
|
||||
if Qd.EmptyRgn(region):
|
||||
return
|
||||
Qd.EraseRgn(region)
|
||||
self.ted.WEUpdate(region)
|
||||
self.updatescrollbars()
|
||||
|
||||
def do_postresize(self, width, height, window):
|
||||
l, t, r, b = self.ted.WEGetViewRect()
|
||||
vr = (l, t, l+width-15, t+height-15)
|
||||
self.ted.WESetViewRect(vr)
|
||||
self.wid.InvalWindowRect(vr)
|
||||
ScrolledWindow.do_postresize(self, width, height, window)
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
(what, message, when, where, modifiers) = evt
|
||||
self.ted.WEClick(local, modifiers, when)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.WESelView()
|
||||
(what, message, when, where, modifiers) = event
|
||||
self.ted.WEKey(ord(ch), modifiers)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.ted.WEGetModCount():
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
del self.ted
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
#
|
||||
# First save data
|
||||
#
|
||||
dhandle = self.ted.WEGetText()
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
#
|
||||
# Now save style and soup
|
||||
#
|
||||
oldresfile = Res.CurResFile()
|
||||
try:
|
||||
rf = Res.FSpOpenResFile(self.path, 3)
|
||||
except Res.Error:
|
||||
Res.FSpCreateResFile(self.path, '????', 'TEXT', macfs.smAllScripts)
|
||||
rf = Res.FSpOpenResFile(self.path, 3)
|
||||
styles = Res.Resource('')
|
||||
soup = Res.Resource('')
|
||||
self.ted.WECopyRange(0, 0x3fffffff, None, styles, soup)
|
||||
styles.AddResource('styl', 128, '')
|
||||
soup.AddResource('SOUP', 128, '')
|
||||
Res.CloseResFile(rf)
|
||||
Res.UseResFile(oldresfile)
|
||||
|
||||
self.ted.WEResetModCount()
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
self.ted.WESelView()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECut()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_copy(self):
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECopy()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEPaste()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_clear(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEDelete()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_undo(self):
|
||||
self.ted.WEUndo()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_setfont(self, font):
|
||||
font = Fm.GetFNum(font)
|
||||
self.mysetstyle(WASTEconst.weDoFont, (font, 0, 0, (0,0,0)))
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_modface(self, face):
|
||||
self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoToggleFace,
|
||||
(0, face, 0, (0,0,0)))
|
||||
|
||||
def menu_setface(self, face):
|
||||
self.mysetstyle(WASTEconst.weDoFace|WASTEconst.weDoReplaceFace,
|
||||
(0, face, 0, (0,0,0)))
|
||||
|
||||
def menu_setsize(self, size):
|
||||
self.mysetstyle(WASTEconst.weDoSize, (0, 0, size, (0,0,0)))
|
||||
|
||||
def menu_incsize(self, size):
|
||||
self.mysetstyle(WASTEconst.weDoAddSize, (0, 0, size, (0,0,0)))
|
||||
|
||||
def mysetstyle(self, which, how):
|
||||
self.ted.WESelView()
|
||||
self.ted.WESetStyle(which, how)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def have_selection(self):
|
||||
start, stop = self.ted.WEGetSelection()
|
||||
return start < stop
|
||||
|
||||
def can_paste(self):
|
||||
return self.ted.WECanPaste()
|
||||
|
||||
def can_undo(self):
|
||||
which, redo = self.ted.WEGetUndoInfo()
|
||||
which = UNDOLABELS[which]
|
||||
if which == None: return None
|
||||
if redo:
|
||||
return "Redo "+which
|
||||
else:
|
||||
return "Undo "+which
|
||||
|
||||
def getruninfo(self):
|
||||
all = (WASTEconst.weDoFont | WASTEconst.weDoFace | WASTEconst.weDoSize)
|
||||
dummy, mode, (font, face, size, color) = self.ted.WEContinuousStyle(all)
|
||||
if not (mode & WASTEconst.weDoFont):
|
||||
font = None
|
||||
else:
|
||||
font = Fm.GetFontName(font)
|
||||
if not (mode & WASTEconst.weDoFace): fact = None
|
||||
if not (mode & WASTEconst.weDoSize): size = None
|
||||
return font, face, size
|
||||
|
||||
class Wed(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
waste.STDObjectHandlers()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
self.makefontmenu()
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem,
|
||||
self.editmenu, self.fontmenu, self.facemenu, self.sizemenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
self.undo_label = "never"
|
||||
self.ffs_values = ()
|
||||
|
||||
def makefontmenu(self):
|
||||
self.fontmenu = Menu(self.menubar, "Font")
|
||||
self.fontnames = getfontnames()
|
||||
self.fontitems = []
|
||||
for n in self.fontnames:
|
||||
m = MenuItem(self.fontmenu, n, "", self.selfont)
|
||||
self.fontitems.append(m)
|
||||
self.facemenu = Menu(self.menubar, "Style")
|
||||
self.faceitems = []
|
||||
for n, shortcut in STYLES:
|
||||
m = MenuItem(self.facemenu, n, shortcut, self.selface)
|
||||
self.faceitems.append(m)
|
||||
self.facemenu.addseparator()
|
||||
self.faceitem_normal = MenuItem(self.facemenu, "Normal", "N",
|
||||
self.selfacenormal)
|
||||
self.sizemenu = Menu(self.menubar, "Size")
|
||||
self.sizeitems = []
|
||||
for n in SIZES:
|
||||
m = MenuItem(self.sizemenu, repr(n), "", self.selsize)
|
||||
self.sizeitems.append(m)
|
||||
self.sizemenu.addseparator()
|
||||
self.sizeitem_bigger = MenuItem(self.sizemenu, "Bigger", "+",
|
||||
self.selsizebigger)
|
||||
self.sizeitem_smaller = MenuItem(self.sizemenu, "Smaller", "-",
|
||||
self.selsizesmaller)
|
||||
|
||||
def selfont(self, id, item, *rest):
|
||||
if self.active:
|
||||
font = self.fontnames[item-1]
|
||||
self.active.menu_setfont(font)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selface(self, id, item, *rest):
|
||||
if self.active:
|
||||
face = (1<<(item-1))
|
||||
self.active.menu_modface(face)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selfacenormal(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_setface(0)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsize(self, id, item, *rest):
|
||||
if self.active:
|
||||
size = SIZES[item-1]
|
||||
self.active.menu_setsize(size)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsizebigger(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_incsize(2)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def selsizesmaller(self, *rest):
|
||||
if self.active:
|
||||
self.active.menu_incsize(-2)
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_paste()
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_undo()
|
||||
if on <> self.undo_label:
|
||||
if on:
|
||||
self.undoitem.enable(1)
|
||||
self.undoitem.settext(on)
|
||||
self.undo_label = on
|
||||
else:
|
||||
self.undoitem.settext("Nothing to undo")
|
||||
self.undoitem.enable(0)
|
||||
changed = 1
|
||||
if self.updatefontmenus():
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
def updatefontmenus(self):
|
||||
info = self.active.getruninfo()
|
||||
if info == self.ffs_values:
|
||||
return 0
|
||||
# Remove old checkmarks
|
||||
if self.ffs_values == ():
|
||||
self.ffs_values = (None, None, None)
|
||||
font, face, size = self.ffs_values
|
||||
if font <> None:
|
||||
fnum = self.fontnames.index(font)
|
||||
self.fontitems[fnum].check(0)
|
||||
if face <> None:
|
||||
for i in range(len(self.faceitems)):
|
||||
if face & (1<<i):
|
||||
self.faceitems[i].check(0)
|
||||
if size <> None:
|
||||
for i in range(len(self.sizeitems)):
|
||||
if SIZES[i] == size:
|
||||
self.sizeitems[i].check(0)
|
||||
|
||||
self.ffs_values = info
|
||||
# Set new checkmarks
|
||||
font, face, size = self.ffs_values
|
||||
if font <> None:
|
||||
fnum = self.fontnames.index(font)
|
||||
self.fontitems[fnum].check(1)
|
||||
if face <> None:
|
||||
for i in range(len(self.faceitems)):
|
||||
if face & (1<<i):
|
||||
self.faceitems[i].check(1)
|
||||
if size <> None:
|
||||
for i in range(len(self.sizeitems)):
|
||||
if SIZES[i] == size:
|
||||
self.sizeitems[i].check(1)
|
||||
# Set outline/normal for sizes
|
||||
if font:
|
||||
exists = getfontsizes(font, SIZES)
|
||||
for i in range(len(self.sizeitems)):
|
||||
if exists[i]:
|
||||
self.sizeitems[i].setstyle(0)
|
||||
else:
|
||||
self.sizeitems[i].setstyle(8)
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor based on WASTE")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = WasteWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_undo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, event):
|
||||
if self.active:
|
||||
self.active.do_idle(event)
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def getfontnames():
|
||||
names = []
|
||||
for i in range(256):
|
||||
n = Fm.GetFontName(i)
|
||||
if n: names.append(n)
|
||||
return names
|
||||
|
||||
def getfontsizes(name, sizes):
|
||||
exist = []
|
||||
num = Fm.GetFNum(name)
|
||||
for sz in sizes:
|
||||
if Fm.RealFont(num, sz):
|
||||
exist.append(1)
|
||||
else:
|
||||
exist.append(0)
|
||||
return exist
|
||||
|
||||
def main():
|
||||
App = Wed()
|
||||
App.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,426 +0,0 @@
|
|||
# A minimal text editor.
|
||||
#
|
||||
# To be done:
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Carbon.Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Qd
|
||||
from Carbon import Res
|
||||
import waste
|
||||
import WASTEconst
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
import EasyDialogs
|
||||
|
||||
UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
|
||||
None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
|
||||
|
||||
BIGREGION=Qd.NewRgn()
|
||||
Qd.SetRectRgn(BIGREGION, -16000, -16000, 16000, 16000)
|
||||
|
||||
class WasteWindow(ScrolledWindow):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
vr = 0, 0, r[2]-r[0]-15, r[3]-r[1]-15
|
||||
dr = (0, 0, 10240, 0)
|
||||
Qd.SetPort(w)
|
||||
Qd.TextFont(4)
|
||||
Qd.TextSize(9)
|
||||
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite | \
|
||||
WASTEconst.weDoMonoStyled | WASTEconst.weDoUndo
|
||||
self.ted = waste.WENew(dr, vr, flags)
|
||||
self.tedtexthandle = Res.Resource(data)
|
||||
self.ted.WEUseText(self.tedtexthandle)
|
||||
self.ted.WECalText()
|
||||
w.DrawGrowIcon()
|
||||
self.scrollbars()
|
||||
self.changed = 0
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def do_idle(self, event):
|
||||
(what, message, when, where, modifiers) = event
|
||||
Qd.SetPort(self.wid)
|
||||
self.ted.WEIdle()
|
||||
if self.ted.WEAdjustCursor(where, BIGREGION):
|
||||
return
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def getscrollbarvalues(self):
|
||||
dr = self.ted.WEGetDestRect()
|
||||
vr = self.ted.WEGetViewRect()
|
||||
vx = self.scalebarvalue(dr[0], dr[2], vr[0], vr[2])
|
||||
vy = self.scalebarvalue(dr[1], dr[3], vr[1], vr[3])
|
||||
## print dr, vr, vx, vy
|
||||
return vx, vy
|
||||
|
||||
def scrollbar_callback(self, which, what, value):
|
||||
if which == 'y':
|
||||
if what == 'set':
|
||||
height = self.ted.WEGetHeight(0, 0x3fffffff)
|
||||
cur = self.getscrollbarvalues()[1]
|
||||
delta = (cur-value)*height/32767
|
||||
if what == '-':
|
||||
topline_off,dummy = self.ted.WEGetOffset((1,1))
|
||||
topline_num = self.ted.WEOffsetToLine(topline_off)
|
||||
delta = self.ted.WEGetHeight(topline_num, topline_num+1)
|
||||
elif what == '--':
|
||||
delta = (self.ted.WEGetViewRect()[3]-10)
|
||||
if delta <= 0:
|
||||
delta = 10 # Random value
|
||||
elif what == '+':
|
||||
# XXXX Wrong: should be bottom line size
|
||||
topline_off,dummy = self.ted.WEGetOffset((1,1))
|
||||
topline_num = self.ted.WEOffsetToLine(topline_off)
|
||||
delta = -self.ted.WEGetHeight(topline_num, topline_num+1)
|
||||
elif what == '++':
|
||||
delta = -(self.ted.WEGetViewRect()[3]-10)
|
||||
if delta >= 0:
|
||||
delta = -10
|
||||
self.ted.WEScroll(0, delta)
|
||||
## print 'SCROLL Y', delta
|
||||
else:
|
||||
if what == 'set':
|
||||
return # XXXX
|
||||
vr = self.ted.WEGetViewRect()
|
||||
winwidth = vr[2]-vr[0]
|
||||
if what == '-':
|
||||
delta = winwidth/10
|
||||
elif what == '--':
|
||||
delta = winwidth/2
|
||||
elif what == '+':
|
||||
delta = -winwidth/10
|
||||
elif what == '++':
|
||||
delta = -winwidth/2
|
||||
self.ted.WEScroll(delta, 0)
|
||||
# Pin the scroll
|
||||
l, t, r, b = self.ted.WEGetDestRect()
|
||||
vl, vt, vr, vb = self.ted.WEGetViewRect()
|
||||
if t > 0 or l > 0:
|
||||
dx = dy = 0
|
||||
if t > 0: dy = -t
|
||||
if l > 0: dx = -l
|
||||
## print 'Extra scroll', dx, dy
|
||||
self.ted.WEScroll(dx, dy)
|
||||
elif b < vb:
|
||||
## print 'Extra downscroll', b-vb
|
||||
self.ted.WEScroll(0, b-vb)
|
||||
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
## print "ACTIVATE", onoff
|
||||
Qd.SetPort(self.wid)
|
||||
ScrolledWindow.do_activate(self, onoff, evt)
|
||||
if onoff:
|
||||
self.ted.WEActivate()
|
||||
self.parent.active = self
|
||||
self.parent.updatemenubar()
|
||||
else:
|
||||
self.ted.WEDeactivate()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
region = wid.GetWindowPort().visRgn
|
||||
if Qd.EmptyRgn(region):
|
||||
return
|
||||
Qd.EraseRgn(region)
|
||||
self.ted.WEUpdate(region)
|
||||
self.updatescrollbars()
|
||||
|
||||
def do_postresize(self, width, height, window):
|
||||
l, t, r, b = self.ted.WEGetViewRect()
|
||||
vr = (l, t, l+width-15, t+height-15)
|
||||
self.ted.WESetViewRect(vr)
|
||||
self.wid.InvalWindowRect(vr)
|
||||
ScrolledWindow.do_postresize(self, width, height, window)
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
(what, message, when, where, modifiers) = evt
|
||||
self.ted.WEClick(local, modifiers, when)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.WESelView()
|
||||
(what, message, when, where, modifiers) = event
|
||||
self.ted.WEKey(ord(ch), modifiers)
|
||||
self.changed = 1
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.changed:
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
del self.ted
|
||||
del self.tedtexthandle
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
## print 'Saving to ', self.path
|
||||
dhandle = self.ted.WEGetText()
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
self.changed = 0
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
self.ted.WESelView()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECut()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_copy(self):
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
self.ted.WECopy()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEPaste()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_clear(self):
|
||||
self.ted.WESelView()
|
||||
self.ted.WEDelete()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_undo(self):
|
||||
self.ted.WEUndo()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def have_selection(self):
|
||||
start, stop = self.ted.WEGetSelection()
|
||||
return start < stop
|
||||
|
||||
def can_paste(self):
|
||||
return self.ted.WECanPaste()
|
||||
|
||||
def can_undo(self):
|
||||
which, redo = self.ted.WEGetUndoInfo()
|
||||
which = UNDOLABELS[which]
|
||||
if which == None: return None
|
||||
if redo:
|
||||
return "Redo "+which
|
||||
else:
|
||||
return "Undo "+which
|
||||
|
||||
class Wed(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
self.undo_label = "never"
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_paste()
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_undo()
|
||||
if on <> self.undo_label:
|
||||
if on:
|
||||
self.undoitem.enable(1)
|
||||
self.undoitem.settext(on)
|
||||
self.undo_label = on
|
||||
else:
|
||||
self.undoitem.settext("Nothing to undo")
|
||||
self.undoitem.enable(0)
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor based on WASTE")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = WasteWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_undo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, event):
|
||||
if self.active:
|
||||
self.active.do_idle(event)
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def main():
|
||||
App = Wed()
|
||||
App.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
|
@ -1,152 +0,0 @@
|
|||
# Scan an Apple header file, generating a Python file of generator calls.
|
||||
|
||||
import sys
|
||||
import os
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
from scantools import Scanner
|
||||
|
||||
WASTEDIR='/Users/jack/src/waste/C_C++ Headers/'
|
||||
|
||||
if not os.path.exists(WASTEDIR):
|
||||
raise 'Error: not found: %s', WASTEDIR
|
||||
|
||||
OBJECT = "TEHandle"
|
||||
SHORT = "waste"
|
||||
OBJECT = "WEReference"
|
||||
OBJECT2 = "WEObjectReference"
|
||||
|
||||
def main():
|
||||
input = WASTEDIR + "WASTE.h"
|
||||
output = SHORT + "gen.py"
|
||||
defsoutput = os.path.join(os.path.split(TOOLBOXDIR)[0], "WASTEconst.py")
|
||||
scanner = MyScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
## scanner.gentypetest(SHORT+"typetest.py")
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done scanning and generating, now importing the generated code... ==="
|
||||
exec "import " + SHORT + "support"
|
||||
print "=== Done. It's up to you to compile it now! ==="
|
||||
|
||||
#class MyScanner(Scanner_PreUH3):
|
||||
class MyScanner(Scanner):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "Function"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[-1]
|
||||
# This is non-functional today
|
||||
if t == OBJECT and m == "InMode":
|
||||
classname = "Method"
|
||||
listname = "methods"
|
||||
else:
|
||||
t, n, m = arglist[0]
|
||||
if t == OBJECT2 and m == "InMode":
|
||||
classname = "Method2"
|
||||
listname = "methods2"
|
||||
return classname, listname
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("kPascalStackBased = None # workaround for header parsing\n")
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
"WEDispose",
|
||||
"WESetInfo", # Argument type unknown...
|
||||
"WEGetInfo",
|
||||
"WEVersion", # Unfortunately...
|
||||
"WEPut", # XXXX TBD: needs array of flavortypes.
|
||||
"WEGetOneAttribute", # XXXX TBD: output buffer
|
||||
# Incompatible constant definitions
|
||||
"weDoAutoScroll",
|
||||
"weDoOutlineHilite",
|
||||
"weDoReadOnly",
|
||||
"weDoUndo",
|
||||
"weDoIntCutAndPaste",
|
||||
"weDoDragAndDrop",
|
||||
"weDoInhibitRecal",
|
||||
"weDoUseTempMem",
|
||||
"weDoDrawOffscreen",
|
||||
"weDoInhibitRedraw",
|
||||
"weDoMonoStyled",
|
||||
"weDoMultipleUndo",
|
||||
"weDoNoKeyboardSync",
|
||||
"weDoInhibitICSupport",
|
||||
"weDoInhibitColor",
|
||||
]
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
"DragReference", # For now...
|
||||
"UniversalProcPtr",
|
||||
"WEFontIDToNameUPP",
|
||||
"WEFontNameToIDUPP",
|
||||
"WEClickLoopUPP",
|
||||
"WEScrollUPP",
|
||||
"WETSMPreUpdateUPP",
|
||||
"WETSMPostUpdateUPP",
|
||||
"WEPreTrackDragUPP",
|
||||
"WETranslateDragUPP",
|
||||
"WEHiliteDropAreaUPP",
|
||||
"WEDrawTextUPP",
|
||||
"WEDrawTSMHiliteUPP",
|
||||
"WEPixelToCharUPP",
|
||||
"WECharToPixelUPP",
|
||||
"WELineBreakUPP",
|
||||
"WEWordBreakUPP",
|
||||
"WECharByteUPP",
|
||||
"WECharTypeUPP",
|
||||
"WEEraseUPP",
|
||||
"WEFluxUPP",
|
||||
"WENewObjectUPP",
|
||||
"WEDisposeObjectUPP",
|
||||
"WEDrawObjectUPP",
|
||||
"WEClickObjectUPP",
|
||||
"WEStreamObjectUPP",
|
||||
"WEHoverObjectUPP",
|
||||
"WERuler", # XXXX To be done
|
||||
"WERuler_ptr", # ditto
|
||||
"WEParaInfo", # XXXX To be done
|
||||
"WEPrintSession", # XXXX To be done
|
||||
"WEPrintOptions_ptr", # XXXX To be done
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
([("void_ptr", "*", "InMode"), ("SInt32", "*", "InMode")],
|
||||
[("InBuffer", "*", "*")]),
|
||||
|
||||
# WEContinuousStyle
|
||||
([("WEStyleMode", "ioMode", "OutMode"), ("TextStyle", "outTextStyle", "OutMode")],
|
||||
[("WEStyleMode", "*", "InOutMode"), ("TextStyle", "*", "*")]),
|
||||
|
||||
# WECopyRange
|
||||
([('Handle', 'outText', 'InMode'), ('StScrpHandle', 'outStyles', 'InMode'),
|
||||
('WESoupHandle', 'outSoup', 'InMode')],
|
||||
[('OptHandle', '*', '*'), ('OptStScrpHandle', '*', '*'),
|
||||
('OptSoupHandle', '*', '*')]),
|
||||
|
||||
# WEInsert
|
||||
([('StScrpHandle', 'inStyles', 'InMode'), ('WESoupHandle', 'inSoup', 'InMode')],
|
||||
[('OptStScrpHandle', '*', '*'), ('OptSoupHandle', '*', '*')]),
|
||||
|
||||
# WEGetObjectOwner
|
||||
("WEGetObjectOwner",
|
||||
[('WEReference', '*', 'ReturnMode')],
|
||||
[('ExistingWEReference', '*', 'ReturnMode')]),
|
||||
|
||||
# WEFindParagraph
|
||||
([("char_ptr", "inKey", "InMode")],
|
||||
[("stringptr", "*", "*")]),
|
||||
|
||||
# WESetOneAttribute
|
||||
([("void_ptr", "*", "InMode"), ("ByteCount", "*", "InMode")],
|
||||
[("InBuffer", "*", "*")]),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,444 +0,0 @@
|
|||
# This script generates a Python interface for an Apple Macintosh Manager.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# The function specifications are generated by scanning the mamager's header file,
|
||||
# using the "scantools" package (customized for this particular manager).
|
||||
|
||||
import string
|
||||
|
||||
# Declarations that change for each manager
|
||||
MACHEADERFILE = 'WASTE.h' # The Apple header file
|
||||
MODNAME = 'waste' # The name of the module
|
||||
OBJECTNAME = 'waste' # The basic name of the objects used here
|
||||
KIND = 'Ptr' # Usually 'Ptr' or 'Handle'
|
||||
|
||||
# The following is *usually* unchanged but may still require tuning
|
||||
MODPREFIX = MODNAME # The prefix for module-wide routines
|
||||
OBJECTTYPE = "WEReference" # The C type used to represent them
|
||||
OBJECTPREFIX = MODPREFIX + 'Obj' # The prefix for object methods
|
||||
INPUTFILE = 'wastegen.py' # The file generated by the scanner
|
||||
TYPETESTFILE = 'wastetypetest.py' # Another file generated by the scanner
|
||||
OUTPUTFILE = "wastemodule.c" # The file generated by this program
|
||||
|
||||
from macsupport import *
|
||||
|
||||
# Create the type objects
|
||||
WEReference = OpaqueByValueType("WEReference", "wasteObj")
|
||||
ExistingWEReference = OpaqueByValueType("WEReference", "ExistingwasteObj")
|
||||
WEObjectReference = OpaqueByValueType("WEObjectReference", "WEOObj")
|
||||
StScrpHandle = OpaqueByValueType("StScrpHandle", "ResObj")
|
||||
RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
|
||||
EventModifiers = Type("EventModifiers", "H")
|
||||
FlavorType = OSTypeType("FlavorType")
|
||||
WESelector = OSTypeType("WESelector")
|
||||
|
||||
OptHandle = OpaqueByValueType("Handle", "OptResObj")
|
||||
OptSoupHandle = OpaqueByValueType("WESoupHandle", "OptResObj")
|
||||
OptStScrpHandle = OpaqueByValueType("StScrpHandle", "OptResObj")
|
||||
|
||||
WEStyleMode = Type("WEStyleMode", "H")
|
||||
WERulerMode = Type("WERulerMode", "l")
|
||||
WEActionKind = Type("WEActionKind", "h")
|
||||
WEAlignment = Type("WEAlignment", "B")
|
||||
WEEdge = Type("WEEdge", "B")
|
||||
WEDirection = Type("WEDirection", "h")
|
||||
WESoupHandle = OpaqueByValueType("WESoupHandle", "ResObj")
|
||||
WEFontTableHandle = OpaqueByValueType("WEFontTableHandle", "ResObj")
|
||||
WEFontTableHandle
|
||||
WERunInfo = OpaqueType("WERunInfo", "RunInfo")
|
||||
|
||||
AppleEvent = OpaqueType('AppleEvent', 'AEDesc')
|
||||
AppleEvent_ptr = OpaqueType('AppleEvent', 'AEDesc')
|
||||
|
||||
TextStyle = OpaqueType("TextStyle", "TextStyle")
|
||||
TextStyle_ptr = TextStyle
|
||||
LongPt = OpaqueType("LongPt", "LongPt")
|
||||
LongPt_ptr = LongPt
|
||||
LongRect = OpaqueType("LongRect", "LongRect")
|
||||
LongRect_ptr = LongRect
|
||||
|
||||
TextEncodingVariant = Type("TextEncodingVariant", "l")
|
||||
TextEncodingFormat = Type("TextEncodingFormat", "l")
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <%s>""" % MACHEADERFILE + """
|
||||
#include <WEObjectHandlers.h>
|
||||
#include <WETabs.h>
|
||||
|
||||
/* Exported by Qdmodule.c: */
|
||||
extern PyObject *QdRGB_New(RGBColor *);
|
||||
extern int QdRGB_Convert(PyObject *, RGBColor *);
|
||||
|
||||
/* Exported by AEModule.c: */
|
||||
extern PyObject *AEDesc_New(AppleEvent *);
|
||||
extern int AEDesc_Convert(PyObject *, AppleEvent *);
|
||||
|
||||
/* Forward declaration */
|
||||
static PyObject *WEOObj_New(WEObjectReference);
|
||||
static PyObject *ExistingwasteObj_New(WEReference);
|
||||
|
||||
/*
|
||||
** Parse/generate TextStyle records
|
||||
*/
|
||||
static PyObject *
|
||||
TextStyle_New(TextStylePtr itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New,
|
||||
&itself->tsColor);
|
||||
}
|
||||
|
||||
static int
|
||||
TextStyle_Convert(PyObject *v, TextStylePtr p_itself)
|
||||
{
|
||||
long font, face, size;
|
||||
|
||||
if( !PyArg_ParseTuple(v, "lllO&", &font, &face, &size, QdRGB_Convert, &p_itself->tsColor) )
|
||||
return 0;
|
||||
p_itself->tsFont = (short)font;
|
||||
p_itself->tsFace = (Style)face;
|
||||
p_itself->tsSize = (short)size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse/generate RunInfo records
|
||||
*/
|
||||
static PyObject *
|
||||
RunInfo_New(WERunInfo *itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("llhhO&O&", itself->runStart, itself->runEnd, itself->runHeight,
|
||||
itself->runAscent, TextStyle_New, &itself->runStyle, WEOObj_New, itself->runObject);
|
||||
}
|
||||
|
||||
/* Conversion of long points and rects */
|
||||
int
|
||||
LongRect_Convert(PyObject *v, LongRect *r)
|
||||
{
|
||||
return PyArg_Parse(v, "(llll)", &r->left, &r->top, &r->right, &r->bottom);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
LongRect_New(LongRect *r)
|
||||
{
|
||||
return Py_BuildValue("(llll)", r->left, r->top, r->right, r->bottom);
|
||||
}
|
||||
|
||||
int
|
||||
LongPt_Convert(PyObject *v, LongPt *p)
|
||||
{
|
||||
return PyArg_Parse(v, "(ll)", &p->h, &p->v);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
LongPt_New(LongPt *p)
|
||||
{
|
||||
return Py_BuildValue("(ll)", p->h, p->v);
|
||||
}
|
||||
|
||||
/* Stuff for the callbacks: */
|
||||
static PyObject *callbackdict;
|
||||
WENewObjectUPP upp_new_handler;
|
||||
WEDisposeObjectUPP upp_dispose_handler;
|
||||
WEDrawObjectUPP upp_draw_handler;
|
||||
WEClickObjectUPP upp_click_handler;
|
||||
|
||||
static OSErr
|
||||
any_handler(WESelector what, WEObjectReference who, PyObject *args, PyObject **rv)
|
||||
{
|
||||
FlavorType tp;
|
||||
PyObject *key, *func;
|
||||
|
||||
if ( args == NULL ) return errAECorruptData;
|
||||
|
||||
tp = WEGetObjectType(who);
|
||||
|
||||
if( (key=Py_BuildValue("O&O&", PyMac_BuildOSType, tp, PyMac_BuildOSType, what)) == NULL)
|
||||
return errAECorruptData;
|
||||
if( (func = PyDict_GetItem(callbackdict, key)) == NULL ) {
|
||||
Py_DECREF(key);
|
||||
return errAEHandlerNotFound;
|
||||
}
|
||||
Py_INCREF(func);
|
||||
*rv = PyEval_CallObject(func, args);
|
||||
Py_DECREF(func);
|
||||
Py_DECREF(key);
|
||||
if ( *rv == NULL ) {
|
||||
PySys_WriteStderr("--Exception in callback: ");
|
||||
PyErr_Print();
|
||||
return errAEReplyNotArrived;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
my_new_handler(Point *objectSize, WEObjectReference objref)
|
||||
{
|
||||
PyObject *args=NULL, *rv=NULL;
|
||||
OSErr err;
|
||||
|
||||
args=Py_BuildValue("(O&)", WEOObj_New, objref);
|
||||
err = any_handler(weNewHandler, objref, args, &rv);
|
||||
if (!err) {
|
||||
if (!PyMac_GetPoint(rv, objectSize) )
|
||||
err = errAECoercionFail;
|
||||
}
|
||||
if ( args ) {
|
||||
Py_DECREF(args);
|
||||
}
|
||||
if ( rv ) {
|
||||
Py_DECREF(rv);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
my_dispose_handler(WEObjectReference objref)
|
||||
{
|
||||
PyObject *args=NULL, *rv=NULL;
|
||||
OSErr err;
|
||||
|
||||
args=Py_BuildValue("(O&)", WEOObj_New, objref);
|
||||
err = any_handler(weDisposeHandler, objref, args, &rv);
|
||||
if ( args ) {
|
||||
Py_DECREF(args);
|
||||
}
|
||||
if ( rv ) {
|
||||
Py_DECREF(rv);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static pascal OSErr
|
||||
my_draw_handler(const Rect *destRect, WEObjectReference objref)
|
||||
{
|
||||
PyObject *args=NULL, *rv=NULL;
|
||||
OSErr err;
|
||||
|
||||
args=Py_BuildValue("O&O&", PyMac_BuildRect, destRect, WEOObj_New, objref);
|
||||
err = any_handler(weDrawHandler, objref, args, &rv);
|
||||
if ( args ) {
|
||||
Py_DECREF(args);
|
||||
}
|
||||
if ( rv ) {
|
||||
Py_DECREF(rv);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static pascal Boolean
|
||||
my_click_handler(Point hitPt, EventModifiers modifiers,
|
||||
unsigned long clickTime, WEObjectReference objref)
|
||||
{
|
||||
PyObject *args=NULL, *rv=NULL;
|
||||
int retvalue;
|
||||
OSErr err;
|
||||
|
||||
args=Py_BuildValue("O&llO&", PyMac_BuildPoint, hitPt,
|
||||
(long)modifiers, (long)clickTime, WEOObj_New, objref);
|
||||
err = any_handler(weClickHandler, objref, args, &rv);
|
||||
if (!err)
|
||||
retvalue = PyInt_AsLong(rv);
|
||||
else
|
||||
retvalue = 0;
|
||||
if ( args ) {
|
||||
Py_DECREF(args);
|
||||
}
|
||||
if ( rv ) {
|
||||
Py_DECREF(rv);
|
||||
}
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
finalstuff = finalstuff + """
|
||||
/* Return the object corresponding to the window, or NULL */
|
||||
|
||||
PyObject *
|
||||
ExistingwasteObj_New(w)
|
||||
WEReference w;
|
||||
{
|
||||
PyObject *it = NULL;
|
||||
|
||||
if (w == NULL)
|
||||
it = NULL;
|
||||
else
|
||||
WEGetInfo(weRefCon, (void *)&it, w);
|
||||
if (it == NULL || ((wasteObject *)it)->ob_itself != w)
|
||||
it = Py_None;
|
||||
Py_INCREF(it);
|
||||
return it;
|
||||
}
|
||||
"""
|
||||
|
||||
class WEMethodGenerator(OSErrMethodGenerator):
|
||||
"""Similar to MethodGenerator, but has self as last argument"""
|
||||
|
||||
def parseArgumentList(self, args):
|
||||
args, a0 = args[:-1], args[-1]
|
||||
t0, n0, m0 = a0
|
||||
if m0 != InMode:
|
||||
raise ValueError, "method's 'self' must be 'InMode'"
|
||||
self.itself = Variable(t0, "_self->ob_itself", SelfMode)
|
||||
FunctionGenerator.parseArgumentList(self, args)
|
||||
self.argumentList.append(self.itself)
|
||||
|
||||
|
||||
|
||||
class WEObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
def outputCheckNewArg(self):
|
||||
Output("""if (itself == NULL) {
|
||||
PyErr_SetString(waste_Error,"Cannot create null WE");
|
||||
return NULL;
|
||||
}""")
|
||||
def outputInitStructMembers(self):
|
||||
GlobalObjectDefinition.outputInitStructMembers(self)
|
||||
Output("WESetInfo(weRefCon, (void *)&it, itself);")
|
||||
def outputFreeIt(self, itselfname):
|
||||
Output("WEDispose(%s);", itselfname)
|
||||
|
||||
class WEOObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
def outputCheckNewArg(self):
|
||||
Output("""if (itself == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}""")
|
||||
|
||||
variablestuff = """
|
||||
callbackdict = PyDict_New();
|
||||
if (callbackdict == NULL || PyDict_SetItemString(d, "callbacks", callbackdict) != 0)
|
||||
return;
|
||||
upp_new_handler = NewWENewObjectProc(my_new_handler);
|
||||
upp_dispose_handler = NewWEDisposeObjectProc(my_dispose_handler);
|
||||
upp_draw_handler = NewWEDrawObjectProc(my_draw_handler);
|
||||
upp_click_handler = NewWEClickObjectProc(my_click_handler);
|
||||
"""
|
||||
|
||||
|
||||
# From here on it's basically all boiler plate...
|
||||
|
||||
# Test types used for existence
|
||||
## execfile(TYPETESTFILE)
|
||||
|
||||
# Create the generator groups and link them
|
||||
module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff, variablestuff)
|
||||
object = WEObjectDefinition(OBJECTNAME, OBJECTPREFIX, OBJECTTYPE)
|
||||
object2 = WEOObjectDefinition("WEO", "WEOObj", "WEObjectReference")
|
||||
module.addobject(object2)
|
||||
module.addobject(object)
|
||||
|
||||
# Create the generator classes used to populate the lists
|
||||
Function = OSErrFunctionGenerator
|
||||
Method = WEMethodGenerator
|
||||
Method2 = OSErrMethodGenerator
|
||||
|
||||
# Create and populate the lists
|
||||
functions = []
|
||||
methods = []
|
||||
methods2 = []
|
||||
execfile(INPUTFILE)
|
||||
|
||||
# A function written by hand:
|
||||
stdhandlers_body = """
|
||||
OSErr err;
|
||||
// install the sample object handlers for pictures and sounds
|
||||
#define kTypePicture 'PICT'
|
||||
#define kTypeSound 'snd '
|
||||
|
||||
if ( !PyArg_ParseTuple(_args, "") ) return NULL;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypePicture, weNewHandler,
|
||||
(UniversalProcPtr) NewWENewObjectProc(HandleNewPicture), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypePicture, weDisposeHandler,
|
||||
(UniversalProcPtr) NewWEDisposeObjectProc(HandleDisposePicture), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypePicture, weDrawHandler,
|
||||
(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawPicture), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypeSound, weNewHandler,
|
||||
(UniversalProcPtr) NewWENewObjectProc(HandleNewSound), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypeSound, weDrawHandler,
|
||||
(UniversalProcPtr) NewWEDrawObjectProc(HandleDrawSound), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
|
||||
if ((err = WEInstallObjectHandler(kTypeSound, weClickHandler,
|
||||
(UniversalProcPtr) NewWEClickObjectProc(HandleClickSound), NULL)) != noErr)
|
||||
goto cleanup;
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
|
||||
cleanup:
|
||||
return PyMac_Error(err);
|
||||
"""
|
||||
|
||||
inshandler_body = """
|
||||
OSErr err;
|
||||
FlavorType objectType;
|
||||
WESelector selector;
|
||||
PyObject *py_handler;
|
||||
UniversalProcPtr handler;
|
||||
WEReference we = NULL;
|
||||
PyObject *key;
|
||||
|
||||
|
||||
if ( !PyArg_ParseTuple(_args, "O&O&O|O&",
|
||||
PyMac_GetOSType, &objectType,
|
||||
PyMac_GetOSType, &selector,
|
||||
&py_handler,
|
||||
WEOObj_Convert, &we) ) return NULL;
|
||||
|
||||
if ( selector == weNewHandler ) handler = (UniversalProcPtr)upp_new_handler;
|
||||
else if ( selector == weDisposeHandler ) handler = (UniversalProcPtr)upp_dispose_handler;
|
||||
else if ( selector == weDrawHandler ) handler = (UniversalProcPtr)upp_draw_handler;
|
||||
else if ( selector == weClickHandler ) handler = (UniversalProcPtr)upp_click_handler;
|
||||
else return PyMac_Error(weUndefinedSelectorErr);
|
||||
|
||||
if ((key = Py_BuildValue("O&O&",
|
||||
PyMac_BuildOSType, objectType,
|
||||
PyMac_BuildOSType, selector)) == NULL )
|
||||
return NULL;
|
||||
|
||||
PyDict_SetItem(callbackdict, key, py_handler);
|
||||
|
||||
err = WEInstallObjectHandler(objectType, selector, handler, we);
|
||||
if ( err ) return PyMac_Error(err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
"""
|
||||
|
||||
stdhand = ManualGenerator("STDObjectHandlers", stdhandlers_body)
|
||||
inshand = ManualGenerator("WEInstallObjectHandler", inshandler_body)
|
||||
|
||||
|
||||
# Tab hook handlers. Could be parsed from WETabs.h, but this is just as simple.
|
||||
f = Method(OSErr, 'WEInstallTabHooks', (WEReference, 'we', InMode))
|
||||
methods.append(f)
|
||||
f = Method(OSErr, 'WERemoveTabHooks', (WEReference, 'we', InMode))
|
||||
methods.append(f)
|
||||
f = Method(Boolean, 'WEIsTabHooks', (WEReference, 'we', InMode))
|
||||
methods.append(f)
|
||||
f = Method(SInt16, 'WEGetTabSize', (WEReference, 'we', InMode))
|
||||
methods.append(f)
|
||||
f = Method(OSErr, 'WESetTabSize', (SInt16, 'tabWidth', InMode), (WEReference, 'we', InMode))
|
||||
methods.append(f)
|
||||
|
||||
# add the populated lists to the generator groups
|
||||
# (in a different wordl the scan program would generate this)
|
||||
for f in functions: module.add(f)
|
||||
module.add(stdhand)
|
||||
module.add(inshand)
|
||||
for f in methods: object.add(f)
|
||||
for f in methods2: object2.add(f)
|
||||
|
||||
# generate output (open the output file as late as possible)
|
||||
SetOutputFileName(OUTPUTFILE)
|
||||
module.generate()
|
23
setup.py
23
setup.py
|
@ -1095,29 +1095,6 @@ class PyBuildExt(build_ext):
|
|||
extra_link_args=['-framework', 'QuickTime',
|
||||
'-framework', 'Carbon']) )
|
||||
|
||||
# As there is no standardized place (yet) to put
|
||||
# user-installed Mac libraries on OSX, we search for "waste"
|
||||
# in parent directories of the Python source tree. You
|
||||
# should put a symlink to your Waste installation in the
|
||||
# same folder as your python source tree. Or modify the
|
||||
# next few lines:-)
|
||||
waste_incs = find_file("WASTE.h", [],
|
||||
['../'*n + 'waste/C_C++ Headers' for n in (0,1,2,3,4)])
|
||||
waste_libs = find_library_file(self.compiler, "WASTE", [],
|
||||
["../"*n + "waste/Static Libraries" for n in (0,1,2,3,4)])
|
||||
if waste_incs != None and waste_libs != None:
|
||||
exts.append( Extension('waste',
|
||||
['waste/wastemodule.c'] + [
|
||||
os.path.join(srcdir, d) for d in
|
||||
'Mac/Wastemods/WEObjectHandlers.c',
|
||||
'Mac/Wastemods/WETabHooks.c',
|
||||
'Mac/Wastemods/WETabs.c'
|
||||
],
|
||||
include_dirs = waste_incs + [os.path.join(srcdir, 'Mac/Wastemods')],
|
||||
library_dirs = waste_libs,
|
||||
libraries = ['WASTE'],
|
||||
extra_link_args = ['-framework', 'Carbon'],
|
||||
) )
|
||||
|
||||
self.extensions.extend(exts)
|
||||
|
||||
|
|
Loading…
Reference in New Issue