Changeset 25364

Show
Ignore:
Timestamp:
05/08/08 06:27:55 (7 months ago)
Author:
axeld
Message:

* Added a quote_context structure that FillInQuoteTextRuns() can now optionally

use to keep track of the current context. This should not only make it faster,
but may also fix the occasionally seen bug of the previous solution.

* Added a simple diff mode coloring as well - only enabled when quote coloring

is enabled.

* Minor cleanup.

Location:
haiku/trunk/src/apps/mail
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • haiku/trunk/src/apps/mail/Content.cpp

    r22122 r25364  
    9090const rgb_color kHeaderColor = {72, 72, 72, 255}; 
    9191 
    92 const rgb_color kQuoteColors[] = 
    93 { 
    94         {0, 0, 0x80, 0},                // 3rd, 6th, ... quote level color 
    95         {0, 0x80, 0, 0},                // 1st, 4th, ... quote level color 
    96         {0x80, 0, 0, 0}                 // 2nd, ... 
     92const rgb_color kQuoteColors[] = { 
     93        {0, 0, 0x80, 0},                // 3rd, 6th, ... quote level color (blue) 
     94        {0, 0x80, 0, 0},                // 1st, 4th, ... quote level color (green) 
     95        {0x80, 0, 0, 0}                 // 2nd, ... (red) 
    9796}; 
    9897const int32 kNumQuoteColors = 3; 
     98 
     99const rgb_color kDiffColors[] = { 
     100        {0xb0, 0, 0, 0},                // '-', red 
     101        {0, 0x90, 0, 0},                // '+', green 
     102        {0x6a, 0x6a, 0x6a, 0}   // '@@', dark grey 
     103}; 
    99104 
    100105void Unicode2UTF8(int32 c, char **out); 
     
    423428 
    424429 
     430int32 
     431diff_mode(char c) 
     432{ 
     433        if (c == '+') 
     434                return 2; 
     435        if (c == '-') 
     436                return 1; 
     437        if (c == '@') 
     438                return 3; 
     439        if (c == ' ') 
     440                return 0; 
     441 
     442        // everything else ends the diff mode 
     443        return -1; 
     444} 
     445 
     446 
    425447bool 
    426448is_quote_char(char c) 
     
    430452 
    431453 
    432 /** Fills the specified text_run_array with the correct values for the 
    433  *      specified text. 
    434  *      If "view" is NULL, it will assume that "line" lies on a line break, 
    435  *      if not, it will correctly retrieve the number of quotes the current 
    436  *      line already has. 
    437  */ 
    438  
     454/*!     Fills the specified text_run_array with the correct values for the 
     455        specified text. 
     456        If "view" is NULL, it will assume that "line" lies on a line break, 
     457        if not, it will correctly retrieve the number of quotes the current 
     458        line already has. 
     459*/ 
    439460void 
    440 FillInQuoteTextRuns(BTextView *view, const char *line, int32 length, const BFont &font, 
    441         text_run_array *style, int32 maxStyles) 
    442 { 
    443         text_run *runs = style->runs; 
     461FillInQuoteTextRuns(BTextView* view, quote_context* context, const char* line, 
     462        int32 length, const BFont& font, text_run_array* style, int32 maxStyles) 
     463{ 
     464        text_run* runs = style->runs; 
    444465        int32 index = style->count; 
    445466        bool begin;  
    446467        int32 pos = 0; 
     468        int32 diffMode = 0; 
     469        bool inDiff = false; 
     470        bool wasDiff = false; 
    447471        int32 level = 0; 
    448472 
    449473        // get index to the beginning of the current line 
    450474 
    451         if (view != NULL) { 
     475        if (context != NULL) { 
     476                level = context->level; 
     477                diffMode = context->diff_mode; 
     478                begin = context->begin; 
     479                inDiff = context->in_diff; 
     480                wasDiff = context->was_diff; 
     481        } else if (view != NULL) { 
    452482                int32 start, end; 
    453483                view->GetSelection(&end, &end); 
    454484 
    455                 begin = view->TextLength() == 0 || view->ByteAt(view->TextLength() - 1) == '\n'; 
    456  
    457                 // the following line works only reliable when text wrapping is set to off; 
    458                 // so the complicated version actually used here is necessary: 
     485                begin = view->TextLength() == 0 
     486                        || view->ByteAt(view->TextLength() - 1) == '\n'; 
     487 
     488                // the following line works only reliable when text wrapping is set to 
     489                // off; so the complicated version actually used here is necessary: 
    459490                // start = view->OffsetAt(view->CurrentLine()); 
    460491 
     
    473504 
    474505                if (!begin && start < end) { 
    475                         begin = true;   // if there was no text in this line, there may come more nested quotes 
    476  
    477                         for (int32 i = start; i < end; i++) { 
    478                                 if (is_quote_char(text[i])) 
    479                                         level++; 
    480                                 else if (text[i] != ' ' && text[i] != '\t') { 
    481                                         begin = false; 
    482                                         break; 
    483                                 } 
    484                         } 
    485                         if (begin)      // skip leading spaces (tabs & newlines aren't allowed here) 
     506                        begin = true; 
     507                                // if there was no text in this line, there may come 
     508                                // more nested quotes 
     509 
     510                        diffMode = diff_mode(text[start]); 
     511                        if (diffMode == 0) { 
     512                                for (int32 i = start; i < end; i++) { 
     513                                        if (is_quote_char(text[i])) 
     514                                                level++; 
     515                                        else if (text[i] != ' ' && text[i] != '\t') { 
     516                                                begin = false; 
     517                                                break; 
     518                                        } 
     519                                } 
     520                        } else 
     521                                inDiff = true; 
     522 
     523                        if (begin) { 
     524                                // skip leading spaces (tabs & newlines aren't allowed here) 
    486525                                while (line[pos] == ' ') 
    487526                                        pos++; 
     527                        } 
    488528                } 
    489529        } else 
     
    495535                int32 next; 
    496536                if (begin && is_quote_char(line[pos])) { 
     537                        begin = false; 
     538 
    497539                        while (pos < length && line[pos] != '\n') { 
     540                                // insert style for each quote level 
    498541                                level++; 
    499542 
     
    503546                                                || line[next] == '\n') 
    504547                                                break; 
    505                                         else if (line[next] != ' ' && line[next] != '\t') 
     548                                        else if (search && line[next] != ' ' && line[next] != '\t') 
    506549                                                search = false; 
    507550                                } 
     
    509552                                runs[index].offset = pos; 
    510553                                runs[index].font = font; 
    511                                 runs[index].color = level > 0 ? kQuoteColors[level % kNumQuoteColors] : kNormalTextColor; 
     554                                runs[index].color = level > 0 
     555                                        ? kQuoteColors[level % kNumQuoteColors] : kNormalTextColor; 
    512556 
    513557                                pos = next; 
     
    516560                        } 
    517561                } else { 
     562                        if (begin) { 
     563                                if (!inDiff) { 
     564                                        inDiff = !strncmp(&line[pos], "--- ", 4); 
     565                                        wasDiff = false; 
     566                                } 
     567                                if (inDiff) { 
     568                                        diffMode = diff_mode(line[pos]); 
     569                                        if (diffMode < 0) { 
     570                                                inDiff = false; 
     571                                                wasDiff = true; 
     572                                        } 
     573                                } 
     574                        } 
     575 
    518576                        runs[index].offset = pos; 
    519577                        runs[index].font = font; 
    520                         runs[index].color = level > 0 ? kQuoteColors[level % kNumQuoteColors] : kNormalTextColor; 
     578                        if (wasDiff) 
     579                                runs[index].color = kDiffColors[diff_mode('@') - 1]; 
     580                        else if (diffMode <= 0) { 
     581                                runs[index].color = level > 0 
     582                                        ? kQuoteColors[level % kNumQuoteColors] : kNormalTextColor; 
     583                        } else 
     584                                runs[index].color = kDiffColors[diffMode - 1]; 
     585 
     586                        begin = false; 
     587 
     588                        for (next = pos; next < length; next++) { 
     589                                if (line[next] == '\n') { 
     590                                        begin = true; 
     591                                        wasDiff = false; 
     592                                        break; 
     593                                } 
     594                        } 
     595 
     596                        pos = next; 
    521597                        index++; 
    522  
    523                         for (next = pos; next < length; next++) { 
    524                                 if (line[next] == '\n') 
    525                                         break; 
    526                         } 
    527                         pos = next; 
     598                } 
     599 
     600                if (pos < length) 
     601                        begin = line[pos] == '\n'; 
     602 
     603                if (begin) { 
     604                        pos++; 
     605                        level = 0; 
     606                        wasDiff = false; 
     607 
     608                        // skip one leading space (tabs & newlines aren't allowed here) 
     609                        if (!inDiff && pos < length && line[pos] == ' ') 
     610                                pos++; 
    528611                } 
    529612 
    530613                if (index >= maxStyles) 
    531614                        break; 
    532  
    533                 level = 0; 
    534  
    535                 if (pos < length && line[pos] == '\n') { 
    536                         pos++; 
    537                         begin = true; 
    538  
    539                         // skip leading spaces (tabs & newlines aren't allowed here) 
    540                         while (pos < length && line[pos] == ' ') 
    541                                 pos++; 
    542                 } 
    543615        } 
    544616        style->count = index; 
     617 
     618        if (context) { 
     619                // update context for next run 
     620                context->level = level; 
     621                context->diff_mode = diffMode; 
     622                context->begin = begin; 
     623                context->in_diff = inDiff; 
     624                context->was_diff = wasDiff; 
     625        } 
    545626} 
    546627 
     
    21722253 
    21732254 
    2174 //-------------------------------------------------------------------- 
    21752255//      #pragma mark - 
    21762256 
    21772257 
    2178 TTextView::Reader::Reader(bool header, bool raw, bool quote, bool incoming, bool stripHeader, 
    2179         bool mime, TTextView *view, BEmailMessage *mail, BList *list, sem_id sem) 
     2258TTextView::Reader::Reader(bool header, bool raw, bool quote, bool incoming, 
     2259                bool stripHeader, bool mime, TTextView *view, BEmailMessage *mail, 
     2260                BList *list, sem_id sem) 
    21802261        : 
    21812262        fHeader(header), 
     
    21942275 
    21952276bool 
    2196 TTextView::Reader::ParseMail(BMailContainer *container, BTextMailComponent *ignore) 
     2277TTextView::Reader::ParseMail(BMailContainer *container, 
     2278        BTextMailComponent *ignore) 
    21972279{ 
    21982280        int32 count = 0; 
     
    23382420 
    23392421bool 
    2340 TTextView::Reader::Insert(const char *line, int32 count, bool isHyperLink, bool isHeader) 
     2422TTextView::Reader::Insert(const char *line, int32 count, bool isHyperLink, 
     2423        bool isHeader) 
    23412424{ 
    23422425        if (!count) 
     
    23462429        TextRunArray style(count / 8 + 8); 
    23472430 
    2348         if (fView->fColoredQuotes && !isHeader && !isHyperLink) 
    2349                 FillInQuoteTextRuns(fView, line, count, font, &style.Array(), style.MaxEntries()); 
    2350         else { 
     2431        if (fView->fColoredQuotes && !isHeader && !isHyperLink) { 
     2432                FillInQuoteTextRuns(fView, &fQuoteContext, line, count, font, 
     2433                        &style.Array(), style.MaxEntries()); 
     2434        } else { 
    23512435                text_run_array &array = style.Array(); 
    23522436                array.count = 1; 
     
    23552439                        array.runs[0].color = isHyperLink ? kHyperLinkColor : kHeaderColor; 
    23562440                        font.SetSize(font.Size() * 0.9); 
    2357                 } else 
    2358                         array.runs[0].color = isHyperLink ? kHyperLinkColor : kNormalTextColor; 
     2441                } else { 
     2442                        array.runs[0].color = isHyperLink 
     2443                                ? kHyperLinkColor : kNormalTextColor; 
     2444                } 
    23592445                array.runs[0].font = font; 
    23602446        } 
     
    30623148                TextRunArray style(targetLength / 8 + 8); 
    30633149 
    3064                 FillInQuoteTextRuns(NULL, target, targetLength, font, &style.Array(), style.MaxEntries()); 
     3150                FillInQuoteTextRuns(NULL, NULL, target, targetLength, font, 
     3151                        &style.Array(), style.MaxEntries()); 
    30653152                Insert(target, targetLength, &style.Array()); 
    30663153        } else 
     
    31393226                        TextRunArray style(length / 8 + 8); 
    31403227 
    3141                         FillInQuoteTextRuns(NULL, target, length, font, &style.Array(), style.MaxEntries()); 
     3228                        FillInQuoteTextRuns(NULL, NULL, target, length, font, 
     3229                                &style.Array(), style.MaxEntries()); 
    31423230                        Insert(target, length, &style.Array()); 
    31433231                } else 
  • haiku/trunk/src/apps/mail/Content.h

    r22122 r25364  
    3232All rights reserved. 
    3333*/ 
    34  
    35 //-------------------------------------------------------------------- 
    36 //       
    37 //      Content.h 
    38 //       
    39 //-------------------------------------------------------------------- 
    40  
    4134#ifndef _CONTENT_H 
    4235#define _CONTENT_H 
     
    7366struct text_run_array; 
    7467 
    75 typedef struct 
    76 { 
     68typedef struct { 
    7769        bool header; 
    7870        bool raw; 
     
    8779} reader_info; 
    8880 
    89 enum ENCLOSURE_TYPE 
    90 { 
     81enum ENCLOSURE_TYPE { 
    9182        TYPE_ENCLOSURE = 100, 
    9283        TYPE_BE_ENCLOSURE, 
     
    114105//==================================================================== 
    115106 
    116 class TContentView : public BView 
    117 { 
     107class TContentView : public BView { 
    118108        public: 
    119109                TContentView(BRect, bool incoming, BEmailMessage *mail, BFont*, 
     
    139129}; 
    140130 
    141 class TTextView : public BTextView 
    142 { 
     131struct quote_context { 
     132        quote_context() 
     133                : 
     134                level(0), 
     135                diff_mode(0), 
     136                begin(true), 
     137                in_diff(false), 
     138                was_diff(false) 
     139        { 
     140        } 
     141 
     142        int32   level; 
     143        int32   diff_mode; 
     144        bool    begin; 
     145        bool    in_diff; 
     146        bool    was_diff; 
     147}; 
     148 
     149class TTextView : public BTextView { 
    143150        public: 
    144151                TTextView(BRect, BRect, bool incoming, BEmailMessage *mail, 
     
    221228                bool fCursor; 
    222229 
    223                 struct spell_mark 
    224                 { 
     230                struct spell_mark { 
    225231                        spell_mark *next; 
    226232                        int32   start; 
     
    231237                spell_mark *fFirstSpellMark; 
    232238 
    233                 class Reader 
    234                 { 
     239                class Reader { 
    235240                        public: 
    236                                 Reader(bool header,bool raw,bool quote,bool incoming,bool stripHeaders,bool mime, 
    237                                         TTextView *view,BEmailMessage *mail,BList *list,sem_id sem); 
    238  
    239                                 static status_t Run(void *); 
     241                                Reader(bool header, bool raw, bool quote, bool incoming, 
     242                                        bool stripHeaders, bool mime, TTextView* view, 
     243                                        BEmailMessage* mail, BList* list, sem_id sem); 
     244 
     245                                static status_t Run(void* _dummy); 
    240246 
    241247                        private: 
    242                                 bool ParseMail(BMailContainer *container,BTextMailComponent *ignore); 
    243                                 bool Process(const char *data, int32 len, bool isHeader = false); 
    244                                 bool Insert(const char *line, int32 count, bool isHyperLink, bool isHeader = false); 
     248                                bool ParseMail(BMailContainer* container, 
     249                                        BTextMailComponent* ignore); 
     250                                bool Process(const char* data, int32 length, 
     251                                        bool isHeader = false); 
     252                                bool Insert(const char* line, int32 count, bool isHyperLink, 
     253                                        bool isHeader = false); 
    245254 
    246255                                bool Lock(); 
     
    250259                                bool fRaw; 
    251260                                bool fQuote; 
     261                                quote_context fQuoteContext; 
    252262                                bool fIncoming; 
    253263                                bool fStripHeader; 
    254264                                bool fMime; 
    255                                 TTextView *fView; 
    256                                 BEmailMessage *fMail; 
     265                                TTextView* fView; 
     266                                BEmailMessage* fMail; 
    257267                                BList *fEnclosures; 
    258268                                sem_id fStopSem; 
     
    289299}; 
    290300 
    291 extern void FillInQuoteTextRuns(BTextView *view, const char *line, int32 length, 
    292                                 const BFont &font, text_run_array *style, int32 maxStyles = 5); 
     301extern void FillInQuoteTextRuns(BTextView* view, quote_context* context, 
     302        const char* line, int32 length, const BFont& font, text_run_array* style, 
     303        int32 maxStyles = 5); 
    293304 
    294305#endif  /* #ifndef _CONTENT_H */ 
  • haiku/trunk/src/apps/mail/MailWindow.cpp

    r24851 r25364  
    21702170                        TextRunArray style(length / 8 + 8); 
    21712171 
    2172                         FillInQuoteTextRuns(fContentView->fTextView, fContentView->fTextView->Text(), 
    2173                                 length, font, &style.Array(), style.MaxEntries()); 
     2172                        FillInQuoteTextRuns(fContentView->fTextView, NULL, 
     2173                                fContentView->fTextView->Text(), length, font, &style.Array(), 
     2174                                style.MaxEntries()); 
    21742175 
    21752176                        fContentView->fTextView->SetRunArray(0, length, &style.Array());