DisplayAgentThreadsV3-Customize-Date-Time

From 40tude Dialog Wiki

Contents

Display Threads in Agent-/Xnews-Style (V3) & Customize Date/Time

This is an improved version of Display Threads in Agent-/Xnews-Style (V2) & Shortening the date-column.


Changes


Example

That's just one possibility (of several) of what you can get:

Display-agent-threads-v3a.png


Installation & Setup

Header layout changes

Use Dialog's Columns Editor (Settings -> Layout -> Edit header list columns, or just right click a header title) to change the header list column's definitions as follows:

You may set attributes for 'Subject' and 'Name' like this (YMMV):

You may set attributes for 'Date' like this (YMMV):

Installation

Paste the script in Event scripts -> OnArticleListPaint, save, configure (as described below), compile and run.

Setup

Have a close look at the 'const' section in the source code below. The settings and their effects are described there. Please check the configuration carefully as the script may produce unpredictable results if not properly configured - although it's very unlikely that the script will damage your installation or data.  ;o)


Warning

Please read the Painting script warning page before trying out this script.


The Script


program OnArticleListPaint;

// Version : 1.5
// Date    : 11.07.2006
// Dialog  : 2.0.15.1 beta 38
//
// 1.2     Amended for 2.0.13.1 beta 36
// 1.3     += doesn't fail if '(' in subject (by Dirk Straka)
// 1.4     += format date string             (by Dirk Straka)
// 1.4.1   += Subject_was_only()             (by Dirk Straka)
// 1.4.2   += TODAYSTR <none>                (by Dirk Straka)
// 1.4.3   -= bug (failed with '(<anything>)' in author's name)
//         += correct subject changes without 'was: ' will be shown, too
//                                           (by Dirk Straka)
// 1.4.4   += format date string with 'Yesterday'
//                                           (by Maik Prinz)
// 1.5     += format date string with 'n days ago' or weekday's name
//                                           (by Dirk Straka)
// 
// Remarks: - Set subject column to "%subjectnamechange%"
//            and name column to "%threadindent%%fromname%"
//            It's recommended to set date column's alignment to 'right'
//
//          - Subject_was_only() does not need any From column.
//
//        --> adjust column indexes and date format below ... <--
//

const
   //
   // - configure column number of columns here.
   // - if you don't have a <from> column,
   //   just set it's index to zero (0).
   //
   n_subject_column = 3;             // <-- set subject column here!
   n_from_column    = 4;             // <-- set from column here!
   n_date_column    = 5;             // <-- set date column here!

   //
   // If you like to use dialog's default thread view (i. e. show
   // '<subject> (<from>)' on subject changes), but want to see subjects
   // of "correct" subject changes only (i. e. containing "was: "),
   // then set this value to TRUE;  normal FUp's display <from> only.
   // BTW:  Subjects containing "Re: " _and_ "was: " will be suppressed,
   // too (as they seem to be incorrect replies):
   //
   // If set to FALSE, only <from> will be shown.
   //
   SHOW_SUBJECT_ON_CHANGE = TRUE;    // set to TRUE or FALSE

   //
   // In DATEFMT you can define how to display the date.
   // Hint:  If you want to add normal text, use double quotes like this:
   //            DATEFMT = '"Date:" dd.mm.yy ("Time:" hh:nn)';
   //        If you want to see a single quote ('), use two, like this:
   //            DATEFMT = '"Date:" dd.mm.yy ("Time:" hh:nn "o''clock")';
   //
   DATEFMT = 'dd.mm.yy    (hh:nn)';  // <-- set preferred date format

   //
   // TODAYSTR and TIMEFMT:
   //   If TODAYSTR is filled with a string,
   //      today's date will be replaced by this string;
   //      today's time will be formatted as spec. in TIMEFMT
   //   If TODAYSTR is set to '<none>',
   //      we will display no string for TODAY at all;
   //      today's time will be formatted as spec. in TIMEFMT
   //   If TODAYSTR is empty (''),
   //      today's date & time displays as defined in DATEFMT
   //   If YESTERDAYSTR is set to any non-empty string,
   //      handling will be the same acc. to TODAYSTR
   //
   TIMEFMT = '(hh:nn)';              // <-- set time format for today's msgs
   TODAYSTR = 'Today       ';        // <-- will result in '    Today  (14:23)'
   //TODAYSTR = '<none>';            // <-- will result in '           (14:23)'
   YESTERDAYSTR = 'Yesterday  ';     // <-- will result in 'Yesterday  (14:23)'
   
   //
   // ORDINALDAYS
   //   If ORDINALDAYS is set to a value greater than 0,
   //      this many days back will be shown as e. g. 'n days ago'
   //      or with it's weekday name instead of the article's
   //      absolute date.
   //      Hint:  ORDINALDAYS=1 will be overruled by YESTERDAYSTR!
   //
   ORDINALDAYS = 3;                  // <-- how many days back
   
   // USE_ORDINALS (doesn't matter if ORDINALDAYS is set to 0)
   //   If USE_ORDINALS is set to ...
   //      TRUE:  ORDINALPREFIX and -SUFFIX will be used (e. g. 'n days ago'):
   //      FALSE: WEEKDAY_n will be used (e. g. 'Wed' or 'Wednesday')
   //
   //   ORDDAYPREFIX can be set to any text
   //      and will be shown before the count of days
   //   ORDDAYSUFFIX can be set to any text
   //      and will be shown beyond the count of days.
   //      Thus you can even display
   //         'sent 4 days ago',
   //      by setting ORDDAYPREFIX to 'sent '
   //      and ORDDAYSUFFIX to ' days ago'
   //
   USE_ORDINALS = TRUE;              // <-- results in ordinals e. g. 'n days ago'
   //USE_ORDINALS = FALSE;           // <-- results in weekday's name e. g. 'Wednesday'

   //
   // Settings for USE_ORDINALS = TRUE:  Prefix and suffix
   //
   ORDDAYPREFIX = '';                // <-- text before daycount 'n' in 'n days ago'
   ORDDAYSUFFIX = ' days ago ';      // <-- text beyond daycount 'n' in 'n days ago'

   //
   // Settings for USE_ORDINALS = FALSE:  Weekday's names
   // You can use your own translation, too, of course.
   // The number of blanks following the names depend on your font.
   //
   WEEKDAY_1 = 'Monday     ';
   WEEKDAY_2 = 'Tuesday    ';
   WEEKDAY_3 = 'Wednesd. ';
   WEEKDAY_4 = 'Thursday   ';
   WEEKDAY_5 = 'Friday        ';
   WEEKDAY_6 = 'Saturday    ';
   WEEKDAY_7 = 'Sunday      ';

// ------------------------------------------------------------- //
// ---  No user maintainable parts below this line  ------------ //
// ------------------------------------------------------------- //

//
// Is the line indented?
// Indented lines start with a space
//
function IsIndented( PaintString : WideString ) : Boolean;
var
   c : WideString;

begin
   c := Copy( PaintString, 1, 1 )
   result := (c = ' ');
end;


//
// Is this a correctly changed subject (i. e. contains "(was: "
//
function IsSubjectChange( PaintString : WideString ) : Boolean;
begin
   result := TRUE;
   if not SHOW_SUBJECT_ON_CHANGE then begin
      result := FALSE;
   end
   else begin
      if IsIndented( PaintString ) then begin
         if (    (Pos(' (was: ', PaintString) = 0)    // ... there's no regular subject change ...
             and (Pos(' (war: ', PaintString) = 0)    // ... possibly in german ...
             and (Pos(', was: ', PaintString) = 0)    // ... or with comma ...
             and (Pos(', war: ', PaintString) = 0))   // ... or with german comma.  ;o)
         then begin                                   // no (correct) subject change found
            result := FALSE;                          // thus suppress subject
         end;
         if result and (Pos('Re: ', Trim(PaintString)) = 1) then begin
            result := FALSE;                          // suppress incorrect Re's.
         end;
         if not (Pos('Re: ', Trim(PaintString)) = 1) then begin    // added 04/11/11
            result := TRUE;         // No "^Re: " - seems to be new (or a name), thus show it.
         end;
      end;
   end;
end;


//
// - Prerequisite:  set Subject column to '%subjectnamechange%'
// - Check if there is a subject change, i. e. if there's a "(was: "
//   in the subject (and no "^Re: "),
// - If so, display "<subject> (<from>)", otherwise just "<from>".
// - Strip (<from>) from "<subject> (<from>) if there's an extra
//   from column (n_from_column > 0)
//
// - Will _NOT_ fail if subject has ' (', now.  ;o)
//
function Subject( PaintString : WideString ) : WideString;

var
   bpos  : Integer;           // pos of opening bracket
   pbpos : Integer;           // pos of previous opening bracket
   flen  : Integer;           // length of <from> field
   ilvl  : Integer;           // identation level (i. e. number of leading blanks)
   i     : Integer;           // counter
   s     : WideString;        // copy of 2 PaintString chars

begin
   bpos   := 0;
   pbpos  := 0;
   result := Copy( PaintString, 1, Length(PaintString) );
   for i:=1 to Length( PaintString ) - 1 do begin  // get start of <from> field
      s := Copy( PaintString, i, 2 );
      if s = ' (' then begin
         pbpos := bpos;                            // remember last bracket
         bpos := i;                                // no break, to get the last '('
      end;
      if s = '  ' then ilvl := ilvl + 1;           // indentation levels
   end;
   if s = '))' then bpos := pbpos;                 // Author with bracket in name
   flen := Length( PaintString ) - bpos-2;         // length of <from>

   if IsIndented( PaintString ) then begin         // FollowUp -> strip subject if ...
      if IsSubjectChange( PaintString) then begin  // ... there's no subject change
         result := Copy( PaintString, 1, Length(PaintString) ); // show complete subject
      end
      else begin                                   // print <from> only
         result := '';
         for i:=0 to ilvl do result := result + ' ';
         if bpos > 0
            then result := result + Copy( PaintString, bpos+2, flen )
            else result := Copy( PaintString, 1, Length(PaintString) );
      end;
   end;

   if     (n_from_column > 0) and (bpos > 0)       // have to strip from
      and IsSubjectChange( PaintString )
      and not IsIndented( PaintString )
   then begin
      result := Copy( PaintString, 1, bpos-1 )
   end;
end;


//
// From column = %threadindent%%fromname%
// Blank the column if it has a threadindent char at start
//
function From( PaintString : WideString ) : WideString;
begin
   if IsIndented( PaintString )
      then result := ''
      else result := PaintString;
end;


//
// Format date column following const DATEFMT (resp. TODAYSTR + TIMEFMT)
//
function Date( const PaintString : WideString ) : WideString;
var
   daysago : Integer;
   daystr  : String;
   y       : Word;
   m       : Word;
   d       : Word;
   dow     : Word;

begin
   result := FormatDateTime( DATEFMT, StrToDateTime(PaintString) );      // default

   daysago := Trunc(Now()) - Trunc(StrToDateTime(PaintString));
   case daysago of
    0:                                               // Today
      daystr := TODAYSTR;
    1:                                               // Yesterday
      daystr := YESTERDAYSTR;
    else                                             // 2 or more days ago
      if daysago <= ORDINALDAYS then begin
         if USE_ORDINALS = TRUE then begin
            daystr := ORDDAYPREFIX + IntToStr(daysago) + ORDDAYSUFFIX;
         end
         else begin
            DecodeDateFully( StrToDateTime(PaintString), y, m, d, dow );
            case dow of
               2: daystr := WEEKDAY_1;
               3: daystr := WEEKDAY_2;
               4: daystr := WEEKDAY_3;
               5: daystr := WEEKDAY_4;
               6: daystr := WEEKDAY_5;
               7: daystr := WEEKDAY_6;
               1: daystr := WEEKDAY_7;
            end;
         end;
      end;
   end;

   if not (daystr = '') then begin
      if (daystr = '<none>') then begin
         result := FormatDateTime( TIMEFMT, StrToDateTime(PaintString) );
      end
      else begin
         result := daystr + ' ' + FormatDateTime( TIMEFMT, StrToDateTime(PaintString) );
      end;
   end;
   // result := IntToStr(daysago) + ' | ' + result // uncomment for adjustment purposes
end;


function OnArticleListPaint(
   PaintString : WideString;
   ColumnIndex : Integer
) : Widestring;

begin
   case ColumnIndex of
    n_subject_column:
      result := Subject( PaintString );
    n_from_column:
      result := From( PaintString );
    n_date_column:
      result := Date( PaintString );
    else
      result := PaintString;
   end;
end;


begin
end.



Have fun!  ;o)

Dirk Straka