diff options
| author | mixedpuppy <devnull@localhost> | 2007-12-05 23:06:58 +0000 | 
|---|---|---|
| committer | mixedpuppy <devnull@localhost> | 2007-12-05 23:06:58 +0000 | 
| commit | ffa2c5b99b0eb534498a550d11ac5debc1204c32 (patch) | |
| tree | 7a56a2c74170e09c85b98ecdeebce310d001ad7d /macosx/PlatMacOSX.cxx | |
| parent | a9e5e58a8d7875426b4d6d009254fc6ec191cbba (diff) | |
| download | scintilla-mirror-ffa2c5b99b0eb534498a550d11ac5debc1204c32.tar.gz | |
modified version of adobe OSX patches.  Most of these patches are provided by Adobe, though I've
reorganized a lot of them
- improved drag/drop
- make copy/paste use modern pasteboard api's
- optimized textlayout usage
- reduce assertions for debug builds
- implement IME support
- other minor things
patches are available in openkomodo, which is a good test ground for scintilla osx (until someone
ports SCiTE).
Diffstat (limited to 'macosx/PlatMacOSX.cxx')
| -rw-r--r-- | macosx/PlatMacOSX.cxx | 395 | 
1 files changed, 164 insertions, 231 deletions
| diff --git a/macosx/PlatMacOSX.cxx b/macosx/PlatMacOSX.cxx index 631e0d95e..f8282c5f8 100644 --- a/macosx/PlatMacOSX.cxx +++ b/macosx/PlatMacOSX.cxx @@ -109,29 +109,24 @@ void Font::Release() {  SurfaceImpl::SurfaceImpl() {      bitmapData = NULL; // Release will try and delete bitmapData if != NULL -#ifdef SUPPORT_PORT -    port = NULL; -#endif      gc = NULL; +    textLayout = new QuartzTextLayout(NULL);      Release();  }  SurfaceImpl::~SurfaceImpl() {      Release(); +    delete textLayout;  }  void SurfaceImpl::Release() { +    textLayout->setContext (NULL);      if ( bitmapData != NULL )          {          delete[] bitmapData;          // We only "own" the graphics context if we are a bitmap context          if ( gc != NULL ) CGContextRelease( gc );          } -#ifdef SUPPORT_PORT -    if ( port != NULL && gc != NULL) { -      QDEndCGContext(port, &gc); -    } -#endif      bitmapData = NULL;      gc = NULL; @@ -155,20 +150,13 @@ void SurfaceImpl::Init(WindowID /*wid*/) {      // aquire/release of the context.      Release(); -#ifdef SUPPORT_PORT -    // Note, this seems to be unecessary, I have not seen any functionality loss by -    // doing nothing in this method. - -    WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>(wid)); -    port = GetWindowPort(window); -    QDBeginCGContext(port, &gc); -#endif  }  void SurfaceImpl::Init(SurfaceID sid, WindowID /*wid*/) {      Release();      gc = reinterpret_cast<CGContextRef>( sid );      CGContextSetLineWidth( gc, 1.0 ); +    textLayout->setContext (gc);  }  void SurfaceImpl::InitPixMap(int width, int height, Surface* /*surface_*/, WindowID /*wid*/) { @@ -182,13 +170,12 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface* /*surface_*/, Windo      // create an RGB color space      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); -    assert( colorSpace != NULL ); +    if( colorSpace == NULL ) +        return;      // create the bitmap      bitmapData = new uint8_t[ bitmapByteCount ]; -    assert( bitmapData != NULL ); -    if( bitmapData != NULL ) -        { +    if( bitmapData != NULL ) {          // create the context          gc = CGBitmapContextCreate( bitmapData,                                      width, @@ -198,24 +185,25 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface* /*surface_*/, Windo                                      colorSpace,                                      kCGImageAlphaPremultipliedLast); -        if( gc == NULL ) -            { +        if( gc == NULL ) {              // the context couldn't be created for some reason,              // and we have no use for the bitmap without the context              delete[] bitmapData;              bitmapData = NULL; -            }          } +        textLayout->setContext (gc); +    }      // the context retains the color space, so we can release it      CGColorSpaceRelease( colorSpace ); -    assert( gc != NULL && bitmapData != NULL ); - -    // "Erase" to white -    CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) ); -    CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 ); -    CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) ); +    if ( gc != NULL && bitmapData != NULL ) +    { +        // "Erase" to white +        CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) ); +        CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 ); +        CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) ); +    }  }  void SurfaceImpl::PenColour(ColourAllocated fore) { @@ -244,28 +232,30 @@ CGImageRef SurfaceImpl::GetImage() {      // create an RGB color space      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); -    assert( colorSpace != NULL ); +    if( colorSpace == NULL ) +        return NULL;      const int bitmapBytesPerRow   = ((int) bitmapWidth * BYTES_PER_PIXEL);      const int bitmapByteCount     = (bitmapBytesPerRow * (int) bitmapHeight);      // Create a data provider      CGDataProviderRef dataProvider = CGDataProviderCreateWithData( NULL, bitmapData, bitmapByteCount, NULL ); -    assert( dataProvider != NULL ); - -    // create the CGImage -    CGImageRef image = CGImageCreate( bitmapWidth, -                                   bitmapHeight, -                                   BITS_PER_COMPONENT, -                                   BITS_PER_PIXEL, -                                   bitmapBytesPerRow, -                                   colorSpace, -                                   kCGImageAlphaPremultipliedLast, -                                   dataProvider, -                                   NULL, -                                   0, -                                   kCGRenderingIntentDefault ); -    assert( image != NULL ); +    CGImageRef image = NULL; +    if ( dataProvider != NULL ) +    { +        // create the CGImage +        image = CGImageCreate( bitmapWidth, +                            bitmapHeight, +                            BITS_PER_COMPONENT, +                            BITS_PER_PIXEL, +                            bitmapBytesPerRow, +                            colorSpace, +                            kCGImageAlphaPremultipliedLast, +                            dataProvider, +                            NULL, +                            0, +                            kCGRenderingIntentDefault ); +    }      // the image retains the color space, so we can release it      CGColorSpaceRelease( colorSpace ); @@ -379,8 +369,6 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {          return;          } -    assert( image != NULL ); -      const CGPatternCallbacks drawImageCallbacks = { 0, reinterpret_cast<CGPatternDrawPatternCallback>( drawImageRefCallback ), NULL };      CGPatternRef pattern = CGPatternCreate( image, @@ -392,30 +380,30 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {                                           true,                                           &drawImageCallbacks                                           ); -    assert( pattern != NULL ); - -    // Create a pattern color space -    CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); -    assert( colorSpace != NULL ); - -    CGContextSaveGState( gc ); -    CGContextSetFillColorSpace( gc, colorSpace ); - -    // Unlike the documentation, you MUST pass in a "components" parameter: -    // For coloured patterns it is the alpha value. -    const float alpha = 1.0; -    CGContextSetFillPattern( gc, pattern, &alpha ); -    CGContextFillRect( gc, PRectangleToCGRect( rc ) ); - -    CGContextRestoreGState( gc ); - -    // Free the color space, the pattern and image -    CGColorSpaceRelease( colorSpace ); -    colorSpace = NULL; -    CGPatternRelease( pattern ); -    pattern = NULL; -    CGImageRelease( image ); -    image = NULL; +    if( pattern != NULL ) { + +        // Create a pattern color space +        CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL ); +        if( colorSpace != NULL ) { + +            CGContextSaveGState( gc ); +            CGContextSetFillColorSpace( gc, colorSpace ); + +            // Unlike the documentation, you MUST pass in a "components" parameter: +            // For coloured patterns it is the alpha value. +            const float alpha = 1.0; +            CGContextSetFillPattern( gc, pattern, &alpha ); +            CGContextFillRect( gc, PRectangleToCGRect( rc ) ); +            CGContextRestoreGState( gc ); +            // Free the color space, the pattern and image +            CGColorSpaceRelease( colorSpace ); +        } /* colorSpace != NULL */ +        colorSpace = NULL; +        CGPatternRelease( pattern ); +        pattern = NULL; +        CGImageRelease( image ); +        image = NULL; +    } /* pattern != NULL */  }  void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { @@ -480,20 +468,16 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl      CGContextDrawPath( gc, kCGPathFillStroke );  } -void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, -        ColourAllocated outline, int alphaOutline, int flags) { -    // XXX TODO +void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourAllocated fill, int alphaFill, +                                            ColourAllocated /*outline*/, int /*alphaOutline*/, int /*flags*/) +{      if ( gc ) { -        CGContextBeginPath( gc ); -        //FillColour(fill); -        PenColour(outline); +        ColourDesired colour( fill.AsLong() ); -        // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo) -        // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined -        // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom. -        // TODO: Create some version of PRectangleToCGRect to do this conversion for us? -        CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) ); -        CGContextDrawPath( gc, kCGPathFill ); +        // Set the Fill color to match +        CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 100.0 ); +        CGRect rect = PRectangleToCGRect( rc ); +        CGContextFillRect( gc, rect );      }  } @@ -597,8 +581,6 @@ void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSou          return;          } -    assert( image != NULL ); -      // Now draw the image on the surface      // Some fancy clipping work is required here: draw only inside of rc @@ -616,29 +598,6 @@ void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSou      image = NULL;  } -QuartzTextLayout* SurfaceImpl::GetTextLayout( Font &font_, const char *s, int len ) -{ -    // create the text layout -    QuartzTextLayout* textLayout = new QuartzTextLayout( gc ); -    OSStatus err = textLayout->setText( reinterpret_cast<const UInt8*>( s ), len, ( unicodeMode ? kCFStringEncodingUTF8 : kCFStringEncodingASCII ) ); -    if (err != noErr) { -        fprintf(stderr, "SurfaceImpl::GetTextLayout error calling textLayout->setText %d %s\n", err, unicodeMode?"Invalid UTF8":"Unknown error"); -        if (unicodeMode) -            err = textLayout->setText( reinterpret_cast<const UInt8*>( s ), len, kCFStringEncodingASCII ); -        if (err != noErr) -            return NULL; -    } - -    textLayout->setStyle( *reinterpret_cast<QuartzTextStyle*>( font_.GetID() ) ); - -    // TODO: If I could modify Scintilla to use ATSUHighlightText, this would not be required. -    // However, using this setting makes Scintilla's rendering match TextEdit's (except for the antialiasing rules) -    ATSLineLayoutOptions rendering = kATSLineUseDeviceMetrics; -    textLayout->setControl( kATSULineLayoutOptionsTag, sizeof( rendering ), &rendering ); - -    return textLayout; -} -  void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,                                   ColourAllocated fore, ColourAllocated back) { @@ -656,89 +615,80 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const c  }  void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) { -    PLATFORM_ASSERT( gc != NULL ); -    QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); -    if (!textLayout) return; +    textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); +      // The Quartz RGB fill color influences the ATSUI color      FillColour(fore); -      // Draw the text, with the Y axis flipped      textLayout->draw( rc.left, ybase, true ); - -    // Get rid of the layout object -    delete textLayout; -    textLayout = NULL;  }  void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {      // sample at http://developer.apple.com/samplecode/ATSUICurveAccessDemo/listing1.html      // sample includes use of ATSUGetGlyphInfo which would be better for older      // OSX systems.  We should expand to using that on older systems as well. -    QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); -    if (!textLayout) return; - -    // Get the UNICODE character length -    UniCharCount unicodeLength, unicodePosition; -    OSStatus err; -    err = ATSUGetTextLocation( textLayout->getLayout(), NULL, NULL, NULL, &unicodeLength, NULL ); -    assert( err == noErr ); - -    ATSLayoutRecord *layoutRecords; -    ItemCount numRecords; -    // Get the arrays of glyph information -    verify_noerr( ATSUDirectGetLayoutDataArrayPtrFromTextLayout( -                textLayout->getLayout(), 0, -                kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, -                (void **)&layoutRecords, &numRecords) ); - -    int i, count; -    long position; -    unsigned char uch; -    unsigned char mask; -    FontID fontid = font_.GetID(); - -    for ( unicodePosition = 0, i = 0; i < len && unicodePosition < numRecords; unicodePosition ++ ) { -        if (fontid) { - -            // note: an extra layoutRecord is provided (eg. numRecords will be one -            //       more than unicodeLength).  Each record contains the left x -            //       coordinate, but we need the right x coordinate, so we skip -            //       the first layoutRecord, thus unicodePosition+1. -            position = Fix2Long( layoutRecords[unicodePosition+1].realPos ); -            uch = s[i]; -            positions[i++] = position; - -            // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters, -            // as 1 unicode character can map to multiple UTF8 characters. -            // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF -            // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html -            if ( unicodeMode ) { -                mask = 0xc0; -                count = 1; -                // Add one additonal byte for each extra high order one in the byte -                while ( uch >= mask && count < 8 ) { -                    assert( i < len ); +    for (int i = 0; i < len; i++) +            positions [i] = 0; +             +    // We need the right X coords, so we have to append a char to get the left coord of thast extra char +    char* buf = (char*) malloc (len+1); +    if (!buf) +            return; +             +    memcpy (buf, s, len); +    buf [len] = '.'; +     +    textLayout->setText (reinterpret_cast<const UInt8*>(buf), len+1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID())); +    ATSUGlyphInfoArray* theGlyphInfoArrayPtr; +    ByteCount theArraySize; + +    // Get the GlyphInfoArray +    ATSUTextLayout layout = textLayout->getLayout(); +    if ( noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, NULL)) +    { +        theGlyphInfoArrayPtr = (ATSUGlyphInfoArray *) malloc (theArraySize + sizeof(ItemCount) + sizeof(ATSUTextLayout)); +        if (theGlyphInfoArrayPtr) +        { +            if (noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, theGlyphInfoArrayPtr)) +            { +                // do not count the first item, which is at the beginning of the line +                for ( UniCharCount unicodePosition = 1, i = 0; i < len && unicodePosition < theGlyphInfoArrayPtr->numGlyphs; unicodePosition ++ ) +                { +                    // The ideal position is the x coordinate of the glyph, relative to the beginning of the line +                    int position = (int)( theGlyphInfoArrayPtr->glyphs[unicodePosition].idealX + 0.5 );    // These older APIs return float values +                    unsigned char uch = s[i];                      positions[i++] = position; -                    count ++; -                    mask = mask >> 1 | 0x80; // add an additional one in the highest order position + +                    // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters, +                    // as 1 unicode character can map to multiple UTF8 characters. +                    // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF +                    // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html +                    if ( unicodeMode )  +                    { +                        unsigned char mask = 0xc0; +                        int count = 1; +                        // Add one additonal byte for each extra high order one in the byte +                        while ( uch >= mask && count < 8 )  +                        { +                            positions[i++] = position; +                            count ++; +                            mask = mask >> 1 | 0x80; // add an additional one in the highest order position +                        } +                    }                  } -                assert( count <= 8 );              } -        } else { -        positions[i++] = (i == 0) ? 1 : positions[i-1] + 1; + +            // Free the GlyphInfoArray +            free (theGlyphInfoArrayPtr);          }      } -    verify_noerr( ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords) ); -    // Get rid of the layout object -    delete textLayout; -    textLayout = NULL; +    free (buf);  }  int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {      if (font_.GetID())      { -        QuartzTextLayout* textLayout = GetTextLayout( font_, s, len ); -        if (!textLayout) return 0; +        textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));          // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?          unsigned long actualNumberOfBounds = 0; @@ -748,17 +698,10 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {          if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )          {              Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthText" ); -            // Get rid of the layout object -            delete textLayout; -            textLayout = NULL;              return 0;          }          //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) ); - -        // Get rid of the layout object -        delete textLayout; -        textLayout = NULL;          return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );      }      return 1; @@ -768,8 +711,7 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) {      char str[2] = { ch, '\0' };      if (font_.GetID())      { -        QuartzTextLayout* textLayout = GetTextLayout( font_, str, 1 ); -        if (!textLayout) return 0; +        textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));          // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?          unsigned long actualNumberOfBounds = 0; @@ -779,15 +721,9 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) {          if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )          {              Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthChar" ); -            // Get rid of the layout object -            delete textLayout; -            textLayout = NULL;              return 0;          } -        // Get rid of the layout object -        delete textLayout; -        textLayout = NULL;          return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );      }      else @@ -893,14 +829,15 @@ void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {  }  void SurfaceImpl::SetDBCSMode(int codePage) { -    // TODO: Implement this +    // TODO: Implement this for code pages != UTF-8  }  Surface *Surface::Allocate() {      return new SurfaceImpl(  );  } -Window::~Window() {} +Window::~Window() { +}  void Window::Destroy() {      if (windowRef) { @@ -996,9 +933,7 @@ void Window::Show(bool show) {  void Window::InvalidateAll() {      if ( id ) { -        OSStatus err; -        err = HIViewSetNeedsDisplay( reinterpret_cast<HIViewRef>( id ), true ); -        assert( err == noErr ); +        HIViewSetNeedsDisplay( reinterpret_cast<HIViewRef>( id ), true );      }  } @@ -1006,13 +941,10 @@ void Window::InvalidateRectangle(PRectangle rc) {      if (id) {          // Create a rectangular region          RgnHandle region = NewRgn(); -        assert( region != NULL );          SetRectRgn( region, rc.left, rc.top, rc.right, rc.bottom );          // Make that region invalid -        OSStatus err; -        err = HIViewSetNeedsDisplayInRegion( reinterpret_cast<HIViewRef>( id ), region, true ); -        assert( err == noErr ); +        HIViewSetNeedsDisplayInRegion( reinterpret_cast<HIViewRef>( id ), region, true );          DisposeRgn( region );      }  } @@ -1041,6 +973,8 @@ void Window::SetCursor(Cursor curs) {                  cursor = kThemeResizeLeftRightCursor;                  break;              case cursorVert: +                cursor = kThemeResizeUpDownCursor; +                break;              case cursorReverseArrow:              case cursorUp:              default: @@ -1148,7 +1082,7 @@ private:      int lineHeight;      bool unicodeMode;      int desiredVisibleRows; -    unsigned int maxItemCharacters; +    unsigned int maxItemWidth;      unsigned int aveCharWidth;      Font font;      int maxWidth; @@ -1170,7 +1104,7 @@ public:      void *doubleClickActionData;      ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false), -            desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8), +            desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8),              doubleClickAction(NULL), doubleClickActionData(NULL)      {        if (kScrollBarWidth == 0) @@ -1223,7 +1157,7 @@ void ListBoxImpl::Create(Window &/*parent*/, int /*ctrlID*/, Scintilla::Point /*                           int lineHeight_, bool unicodeMode_) {      lineHeight = lineHeight_;      unicodeMode = unicodeMode_; -    maxWidth = 1000; +    maxWidth = 2000;      WindowClass windowClass = kHelpWindowClass;      WindowAttributes attributes = kWindowNoAttributes; @@ -1501,13 +1435,14 @@ void ListBoxImpl::SetFont(Font &font_) {  #endif      // !@&^#%$ we cant copy Font, but we need one for our custom drawing -    Str255 fontName; -    if (FMGetFontFamilyName(style.font, fontName) != kFMInvalidFontFamilyErr) { -      // make sure we conver to a proper C string first. -      char cFontName[255]; -      CopyPascalStringToC(fontName, cFontName); -      font.Create((const char *)cFontName, 0, style.size, false, false); -    } +    Str255 fontName255; +    char fontName[256]; +    FMGetFontFamilyName(style.font, fontName255); + +    CFStringRef fontNameCF = ::CFStringCreateWithPascalString( kCFAllocatorDefault, fontName255, kCFStringEncodingMacRoman ); +    ::CFStringGetCString( fontNameCF, fontName, (CFIndex)255, kCFStringEncodingMacRoman ); + +    font.Create((const char *)fontName, 0, style.size, false, false);  }  void ListBoxImpl::SetAverageCharWidth(int width) { @@ -1545,17 +1480,14 @@ PRectangle ListBoxImpl::GetDesiredRect() {          rows = desiredVisibleRows;      rcDesired.bottom = itemHeight * rows; -    int width = maxItemCharacters; -    if (width < 12) -        width = 12; -    // XXX use the quartz text stuff to figure out the correct string width -    rcDesired.right = rcDesired.left + width * (aveCharWidth+aveCharWidth/4); -    if (rcDesired.right > maxWidth) { -        rcDesired.right = maxWidth; -    } -    if (Length() > rows) +    rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth; + +    if (Length() > rows)           rcDesired.right += kScrollBarWidth;      rcDesired.right += IconWidth(); + +    // Set the column width +    ::SetDataBrowserTableViewColumnWidth (lb, UInt16 (rcDesired.right - rcDesired.left));      return rcDesired;  } @@ -1578,7 +1510,7 @@ int ListBoxImpl::CaretFromEdge() {  void ListBoxImpl::Clear() {      // passing NULL to "items" arg 4 clears the list -    maxItemCharacters = 0; +    maxItemWidth = 0;      ld.Clear();      AddDataBrowserItems (lb, kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty);  } @@ -1588,15 +1520,15 @@ void ListBoxImpl::Append(char *s, int type) {      CFStringRef r = CFStringCreateWithCString(NULL, s, kTextEncodingMacRoman);      ld.Add(count, type, r); +    Scintilla::SurfaceImpl surface; +    unsigned int width = surface.WidthText (font, s, strlen (s)); +    if (width > maxItemWidth) +        maxItemWidth = width; +      DataBrowserItemID items[1];      items[0] = count + 1;      AddDataBrowserItems (lb, kDataBrowserNoItem, 1, items, kDataBrowserItemNoProperty);      ShowHideScrollbar(); - -    size_t len = strlen(s); -    if (maxItemCharacters < len) -            maxItemCharacters = len; -  }  void ListBoxImpl::SetList(const char* list, char separator, char typesep) { @@ -1721,7 +1653,6 @@ void Menu::CreatePopUp() {      Destroy();      OSStatus err;      err = CreateNewMenu( nextMenuID++, 0, reinterpret_cast<MenuRef*>( &id ) ); -    assert( noErr == err && id != NULL );  }  void Menu::Destroy() { @@ -1746,8 +1677,6 @@ void Menu::Show(Point pt, Window &) {                                  &menuId,                                  &menuItem                                  ); -    // The system should always handle the command for us, so we should get userCanceledErr -    assert( /*noErr == err ||*/ userCanceledErr == err );  }  // TODO: Consider if I should be using GetCurrentEventTime instead of gettimeoday @@ -1755,7 +1684,6 @@ ElapsedTime::ElapsedTime() {      struct timeval curTime;      int retVal;      retVal = gettimeofday( &curTime, NULL ); -    assert( retVal == 0 );      bigBit = curTime.tv_sec;      littleBit = curTime.tv_usec; @@ -1765,7 +1693,6 @@ double ElapsedTime::Duration(bool reset) {      struct timeval curTime;      int retVal;      retVal = gettimeofday( &curTime, NULL ); -    assert( retVal == 0 );      long endBigBit = curTime.tv_sec;      long endLittleBit = curTime.tv_usec;      double result = 1000000.0 * (endBigBit - bigBit); @@ -1794,7 +1721,11 @@ static Str255 PlatformDefaultFontName;  const char *Platform::DefaultFont() {      long id = HighShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize));      FMGetFontFamilyName(id, PlatformDefaultFontName); -    return (const char *)PlatformDefaultFontName; +    char* defaultFontName = (char*) PlatformDefaultFontName; +    defaultFontName[defaultFontName[0]+1] = 0; +    ++defaultFontName; + +    return defaultFontName;  }  int Platform::DefaultFontSize() { @@ -1836,17 +1767,17 @@ long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam,  }  bool Platform::IsDBCSLeadByte(int /*codePage*/, char /*ch*/) { -    // TODO: Implement this +    // TODO: Implement this for code pages != UTF-8      return false;  }  int Platform::DBCSCharLength(int /*codePage*/, const char* /*s*/) { -    // TODO: Implement this +    // TODO: Implement this for code pages != UTF-8      return 1;  }  int Platform::DBCSCharMaxLength() { -    // TODO: Implement this +    // TODO: Implement this for code pages != UTF-8      //return CFStringGetMaximumSizeForEncoding( 1, CFStringEncoding encoding );      return 2;  } @@ -1906,11 +1837,13 @@ void Platform::Assert(const char *c, const char *file, int line) {      sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);      strcat(buffer, "\r\n");      Platform::DebugDisplay(buffer); -    abort(); +#ifdef DEBUG  +    // Jump into debugger in assert on Mac (CL269835) +    ::Debugger(); +#endif  }  int Platform::Clamp(int val, int minVal, int maxVal) { -    assert( minVal <= maxVal );      if (val > maxVal)          val = maxVal;      if (val < minVal) | 
