Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PIM
KAlarm
Commits
b7c64795
Commit
b7c64795
authored
Oct 20, 2011
by
David Jarvie
Browse files
Move from kalarm/cal/ to kalarmcal/
parent
d6e99eb8
Changes
27
Expand all
Hide whitespace changes
Inline
Side-by-side
CMakeLists.txt
0 → 100644
View file @
b7c64795
############### Build Options ###############
# KALARM_USE_KRESOURCES - builds to use KResources instead of Akonadi
#option(KALARM_USE_KRESOURCES "Build to use KResources" OFF)
if
(
NOT KALARM_USE_AKONADI
)
add_definitions
(
-DUSE_KRESOURCES
)
endif
(
NOT KALARM_USE_AKONADI
)
########### next target ###############
set
(
kalarm_calendar_LIB_SRCS
kacalendar.cpp
karecurrence.cpp
alarmtext.cpp
identities.cpp
kaevent.cpp
datetime.cpp
repetition.cpp
version.cpp
)
if
(
NOT KALARM_USE_KRESOURCES
)
set
(
kalarm_calendar_LIB_SRCS
${
kalarm_calendar_LIB_SRCS
}
collectionattribute.cpp
compatibilityattribute.cpp
eventattribute.cpp
)
endif
(
NOT KALARM_USE_KRESOURCES
)
kde4_add_library
(
kalarm_calendar
${
LIBRARY_TYPE
}
${
kalarm_calendar_LIB_SRCS
}
)
if
(
KALARM_USE_KRESOURCES
)
target_link_libraries
(
kalarm_calendar
${
KDEPIMLIBS_KCAL_LIBS
}
${
KDEPIMLIBS_KPIMIDENTITIES_LIBS
}
${
KDEPIMLIBS_KHOLIDAYS_LIBS
}
)
target_link_libraries
(
kalarm_calendar LINK_INTERFACE_LIBRARIES
${
KDEPIMLIBS_KCAL_LIBS
}
${
KDEPIMLIBS_KPIMIDENTITIES_LIBS
}
${
KDEPIMLIBS_KHOLIDAYS_LIBS
}
)
else
(
KALARM_USE_KRESOURCES
)
target_link_libraries
(
kalarm_calendar
${
KDEPIMLIBS_AKONADI_LIBS
}
${
KDEPIMLIBS_KCALCORE_LIBS
}
${
KDEPIMLIBS_KPIMIDENTITIES_LIBS
}
${
KDEPIMLIBS_KHOLIDAYS_LIBS
}
)
target_link_libraries
(
kalarm_calendar LINK_INTERFACE_LIBRARIES
${
KDEPIMLIBS_AKONADI_LIBS
}
${
KDEPIMLIBS_KCAL_LIBS
}
${
KDEPIMLIBS_KPIMIDENTITIES_LIBS
}
${
KDEPIMLIBS_KHOLIDAYS_LIBS
}
)
endif
(
KALARM_USE_KRESOURCES
)
set_target_properties
(
kalarm_calendar PROPERTIES
VERSION
${
GENERIC_LIB_VERSION
}
SOVERSION
${
GENERIC_LIB_SOVERSION
}
)
install
(
TARGETS kalarm_calendar
${
INSTALL_TARGETS_DEFAULT_ARGS
}
)
Mainpage.dox
0 → 100644
View file @
b7c64795
/*!
* @mainpage The KAlarm client library
*
* @section purpose Purpose
*
* This library provides access to and handling of KAlarm calendar data.
*
* @section desc Description
*
* This library provides access to KAlarm calendar data, but not to the storage
* of the data, which is handled by Akonadi (or by build option, KResources).
* The main class, KAEvent represents a KAlarm event, and contains both the
* event definition including the main alarm and optional subsidiary alarms, and
* status information about the event.
*
* Calendar format information is accessed through the KACalendar class, which
* provides read and write access to the calendar format version and
* iCalendar product ID.
*
* Recurrence and sub-repetition information is represented by the KARecurrence
* and Repetition classes respectively. The DateTime class is similar to
* KDateTime but with a configurable start-of-day time for date-only times.
*
* Three Akonadi attributes, for Collections and Items, are provided by
* CollectionAttribute, CompatibilityAttribute and EventAttribute classes.
*
* @authors
* David Jarvie \<djarvie@kde.org\>
*
* @licenses
* @lgpl
*/
// DOXYGEN_PROJECTNAME=KAlarm Library
README
0 → 100644
View file @
b7c64795
See Mainpage.dox for more information.
alarmtext.cpp
0 → 100644
View file @
b7c64795
/*
* alarmtext.cpp - text/email alarm text conversion
* Program: kalarm
* Copyright © 2004,2005,2007-2011 by David Jarvie <djarvie@kde.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include
"alarmtext.h"
#include
"kaevent.h"
#ifdef USE_KRESOURCES
#include
<kcal/todo.h>
#endif
#include
<klocale.h>
#include
<kglobal.h>
#include
<QStringList>
namespace
KAlarm
{
class
AlarmText
::
Private
{
public:
enum
Type
{
None
,
Email
,
Script
,
Todo
};
QString
displayText
()
const
;
void
clear
();
static
void
initialise
();
static
void
setUpTranslations
();
static
int
emailHeaderCount
(
const
QStringList
&
);
static
QString
todoTitle
(
const
QString
&
text
);
static
QString
mFromPrefix
;
// translated header prefixes
static
QString
mToPrefix
;
static
QString
mCcPrefix
;
static
QString
mDatePrefix
;
static
QString
mSubjectPrefix
;
static
QString
mTitlePrefix
;
static
QString
mLocnPrefix
;
static
QString
mDuePrefix
;
static
QString
mFromPrefixEn
;
// untranslated header prefixes
static
QString
mToPrefixEn
;
static
QString
mCcPrefixEn
;
static
QString
mDatePrefixEn
;
static
QString
mSubjectPrefixEn
;
static
bool
mInitialised
;
QString
mBody
,
mFrom
,
mTo
,
mCc
,
mTime
,
mSubject
;
unsigned
long
mKMailSerialNum
;
// if email, message's KMail serial number, else 0
Type
mType
;
bool
mIsEmail
;
};
QString
AlarmText
::
Private
::
mFromPrefix
;
QString
AlarmText
::
Private
::
mToPrefix
;
QString
AlarmText
::
Private
::
mCcPrefix
;
QString
AlarmText
::
Private
::
mDatePrefix
;
QString
AlarmText
::
Private
::
mSubjectPrefix
;
QString
AlarmText
::
Private
::
mTitlePrefix
;
QString
AlarmText
::
Private
::
mLocnPrefix
;
QString
AlarmText
::
Private
::
mDuePrefix
;
QString
AlarmText
::
Private
::
mFromPrefixEn
;
QString
AlarmText
::
Private
::
mToPrefixEn
;
QString
AlarmText
::
Private
::
mCcPrefixEn
;
QString
AlarmText
::
Private
::
mDatePrefixEn
;
QString
AlarmText
::
Private
::
mSubjectPrefixEn
;
bool
AlarmText
::
Private
::
mInitialised
=
false
;
void
AlarmText
::
Private
::
initialise
()
{
if
(
!
mInitialised
)
{
mInitialised
=
true
;
mFromPrefixEn
=
QLatin1String
(
"From:"
);
mToPrefixEn
=
QLatin1String
(
"To:"
);
mCcPrefixEn
=
QLatin1String
(
"Cc:"
);
mDatePrefixEn
=
QLatin1String
(
"Date:"
);
mSubjectPrefixEn
=
QLatin1String
(
"Subject:"
);
}
}
AlarmText
::
AlarmText
(
const
QString
&
text
)
:
d
(
new
Private
)
{
Private
::
initialise
();
setText
(
text
);
}
AlarmText
::
AlarmText
(
const
AlarmText
&
other
)
:
d
(
new
Private
(
*
other
.
d
))
{
}
AlarmText
::~
AlarmText
()
{
delete
d
;
}
AlarmText
&
AlarmText
::
operator
=
(
const
AlarmText
&
other
)
{
if
(
&
other
!=
this
)
*
d
=
*
other
.
d
;
return
*
this
;
}
void
AlarmText
::
setText
(
const
QString
&
text
)
{
d
->
clear
();
d
->
mBody
=
text
;
if
(
text
.
startsWith
(
QLatin1String
(
"#!"
)))
d
->
mType
=
Private
::
Script
;
}
void
AlarmText
::
setScript
(
const
QString
&
text
)
{
setText
(
text
);
d
->
mType
=
Private
::
Script
;
}
void
AlarmText
::
setEmail
(
const
QString
&
to
,
const
QString
&
from
,
const
QString
&
cc
,
const
QString
&
time
,
const
QString
&
subject
,
const
QString
&
body
,
unsigned
long
kmailSerialNumber
)
{
d
->
clear
();
d
->
mType
=
Private
::
Email
;
d
->
mTo
=
to
;
d
->
mFrom
=
from
;
d
->
mCc
=
cc
;
d
->
mTime
=
time
;
d
->
mSubject
=
subject
;
d
->
mBody
=
body
;
d
->
mKMailSerialNum
=
kmailSerialNumber
;
}
#ifndef USE_KRESOURCES
void
AlarmText
::
setTodo
(
const
KCalCore
::
Todo
::
Ptr
&
todo
)
#else
void
AlarmText
::
setTodo
(
const
KCal
::
Todo
*
todo
)
#endif
{
d
->
clear
();
d
->
mType
=
Private
::
Todo
;
d
->
mSubject
=
todo
->
summary
();
d
->
mBody
=
todo
->
description
();
d
->
mTo
=
todo
->
location
();
if
(
todo
->
hasDueDate
())
{
KDateTime
due
=
todo
->
dtDue
(
false
);
// fetch the next due date
if
(
todo
->
hasStartDate
()
&&
todo
->
dtStart
()
!=
due
)
{
d
->
mTime
=
todo
->
allDay
()
?
KGlobal
::
locale
()
->
formatDate
(
due
.
date
(),
KLocale
::
ShortDate
)
:
KGlobal
::
locale
()
->
formatDateTime
(
due
.
dateTime
());
}
}
}
/******************************************************************************
* Return the text for a text message alarm, in display format.
*/
QString
AlarmText
::
displayText
()
const
{
return
d
->
displayText
();
}
QString
AlarmText
::
Private
::
displayText
()
const
{
QString
text
;
switch
(
mType
)
{
case
Email
:
// Format the email into a text alarm
setUpTranslations
();
text
=
mFromPrefix
+
'\t'
+
mFrom
+
'\n'
;
text
+=
mToPrefix
+
'\t'
+
mTo
+
'\n'
;
if
(
!
mCc
.
isEmpty
())
text
+=
mCcPrefix
+
'\t'
+
mCc
+
'\n'
;
if
(
!
mTime
.
isEmpty
())
text
+=
mDatePrefix
+
'\t'
+
mTime
+
'\n'
;
text
+=
mSubjectPrefix
+
'\t'
+
mSubject
;
if
(
!
mBody
.
isEmpty
())
{
text
+=
"
\n\n
"
;
text
+=
mBody
;
}
break
;
case
Todo
:
// Format the todo into a text alarm
setUpTranslations
();
if
(
!
mSubject
.
isEmpty
())
text
=
mTitlePrefix
+
'\t'
+
mSubject
+
'\n'
;
if
(
!
mTo
.
isEmpty
())
text
+=
mLocnPrefix
+
'\t'
+
mTo
+
'\n'
;
if
(
!
mTime
.
isEmpty
())
text
+=
mDuePrefix
+
'\t'
+
mTime
+
'\n'
;
if
(
!
mBody
.
isEmpty
())
{
if
(
!
text
.
isEmpty
())
text
+=
'\n'
;
text
+=
mBody
;
}
break
;
default:
break
;
}
return
!
text
.
isEmpty
()
?
text
:
mBody
;
}
QString
AlarmText
::
to
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mTo
:
QString
();
}
QString
AlarmText
::
from
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mFrom
:
QString
();
}
QString
AlarmText
::
cc
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mCc
:
QString
();
}
QString
AlarmText
::
time
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mTime
:
QString
();
}
QString
AlarmText
::
subject
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mSubject
:
QString
();
}
QString
AlarmText
::
body
()
const
{
return
(
d
->
mType
==
Private
::
Email
)
?
d
->
mBody
:
QString
();
}
QString
AlarmText
::
summary
()
const
{
return
(
d
->
mType
==
Private
::
Todo
)
?
d
->
mSubject
:
QString
();
}
QString
AlarmText
::
location
()
const
{
return
(
d
->
mType
==
Private
::
Todo
)
?
d
->
mTo
:
QString
();
}
QString
AlarmText
::
due
()
const
{
return
(
d
->
mType
==
Private
::
Todo
)
?
d
->
mTime
:
QString
();
}
QString
AlarmText
::
description
()
const
{
return
(
d
->
mType
==
Private
::
Todo
)
?
d
->
mBody
:
QString
();
}
/******************************************************************************
* Return whether there is any text.
*/
bool
AlarmText
::
isEmpty
()
const
{
if
(
!
d
->
mBody
.
isEmpty
())
return
false
;
if
(
d
->
mType
!=
Private
::
Email
)
return
true
;
return
d
->
mFrom
.
isEmpty
()
&&
d
->
mTo
.
isEmpty
()
&&
d
->
mCc
.
isEmpty
()
&&
d
->
mTime
.
isEmpty
()
&&
d
->
mSubject
.
isEmpty
();
}
bool
AlarmText
::
isEmail
()
const
{
return
d
->
mType
==
Private
::
Email
;
}
bool
AlarmText
::
isScript
()
const
{
return
d
->
mType
==
Private
::
Script
;
}
bool
AlarmText
::
isTodo
()
const
{
return
d
->
mType
==
Private
::
Todo
;
}
unsigned
long
AlarmText
::
kmailSerialNumber
()
const
{
return
d
->
mKMailSerialNum
;
}
/******************************************************************************
* Return the alarm summary text for either single line or tooltip display.
* The maximum number of line returned is determined by 'maxLines'.
* If 'truncated' is non-null, it will be set true if the text returned has been
* truncated, other than to strip a trailing newline.
*/
QString
AlarmText
::
summary
(
const
KAEvent
&
event
,
int
maxLines
,
bool
*
truncated
)
{
static
const
QRegExp
localfile
(
"^file:/+"
);
QString
text
;
switch
(
event
.
actionSubType
())
{
case
KAEvent
::
AUDIO
:
text
=
event
.
audioFile
();
if
(
localfile
.
indexIn
(
text
)
>=
0
)
text
=
text
.
mid
(
localfile
.
matchedLength
()
-
1
);
break
;
case
KAEvent
::
EMAIL
:
text
=
event
.
emailSubject
();
break
;
case
KAEvent
::
COMMAND
:
text
=
event
.
cleanText
();
if
(
localfile
.
indexIn
(
text
)
>=
0
)
text
=
text
.
mid
(
localfile
.
matchedLength
()
-
1
);
break
;
case
KAEvent
::
FILE
:
text
=
event
.
cleanText
();
break
;
case
KAEvent
::
MESSAGE
:
{
text
=
event
.
cleanText
();
// If the message is the text of an email, return its headers or just subject line
QString
subject
=
emailHeaders
(
text
,
(
maxLines
<=
1
));
if
(
!
subject
.
isNull
())
{
if
(
truncated
)
*
truncated
=
true
;
return
subject
;
}
if
(
maxLines
==
1
)
{
// If the message is the text of a todo, return either the
// title/description or the whole text.
subject
=
Private
::
todoTitle
(
text
);
if
(
!
subject
.
isEmpty
())
{
if
(
truncated
)
*
truncated
=
true
;
return
subject
;
}
}
break
;
}
}
if
(
truncated
)
*
truncated
=
false
;
if
(
text
.
count
(
'\n'
)
<
maxLines
)
return
text
;
int
newline
=
-
1
;
for
(
int
i
=
0
;
i
<
maxLines
;
++
i
)
{
newline
=
text
.
indexOf
(
'\n'
,
newline
+
1
);
if
(
newline
<
0
)
return
text
;
// not truncated after all !?!
}
if
(
newline
==
static_cast
<
int
>
(
text
.
length
())
-
1
)
return
text
.
left
(
newline
);
// text ends in newline
if
(
truncated
)
*
truncated
=
true
;
return
text
.
left
(
newline
+
(
maxLines
<=
1
?
0
:
1
))
+
QLatin1String
(
"..."
);
}
/******************************************************************************
* Check whether a text is an email.
*/
bool
AlarmText
::
checkIfEmail
(
const
QString
&
text
)
{
QStringList
lines
=
text
.
split
(
'\n'
,
QString
::
SkipEmptyParts
);
return
Private
::
emailHeaderCount
(
lines
);
}
/******************************************************************************
* Check whether a text is an email, and if so return its headers or optionally
* only its subject line.
* Reply = headers/subject line, or QString() if not the text of an email.
*/
QString
AlarmText
::
emailHeaders
(
const
QString
&
text
,
bool
subjectOnly
)
{
QStringList
lines
=
text
.
split
(
'\n'
,
QString
::
SkipEmptyParts
);
int
n
=
Private
::
emailHeaderCount
(
lines
);
if
(
!
n
)
return
QString
();
if
(
subjectOnly
)
return
lines
[
n
-
1
].
mid
(
Private
::
mSubjectPrefix
.
length
()).
trimmed
();
QString
h
=
lines
[
0
];
for
(
int
i
=
1
;
i
<
n
;
++
i
)
{
h
+=
'\n'
;
h
+=
lines
[
i
];
}
return
h
;
}
/******************************************************************************
* Translate an alarm calendar text to a display text.
* Translation is needed for email texts, since the alarm calendar stores
* untranslated email prefixes.
* 'email' is set to indicate whether it is an email text.
*/
QString
AlarmText
::
fromCalendarText
(
const
QString
&
text
,
bool
&
email
)
{
Private
::
initialise
();
QStringList
lines
=
text
.
split
(
'\n'
,
QString
::
SkipEmptyParts
);
int
maxn
=
lines
.
count
();
if
(
maxn
>=
4
&&
lines
[
0
].
startsWith
(
Private
::
mFromPrefixEn
)
&&
lines
[
1
].
startsWith
(
Private
::
mToPrefixEn
))
{
int
n
=
2
;
if
(
lines
[
2
].
startsWith
(
Private
::
mCcPrefixEn
))
++
n
;
if
(
maxn
>
n
+
1
&&
lines
[
n
].
startsWith
(
Private
::
mDatePrefixEn
)
&&
lines
[
n
+
1
].
startsWith
(
Private
::
mSubjectPrefixEn
))
{
Private
::
setUpTranslations
();
QString
dispText
;
dispText
=
Private
::
mFromPrefix
+
lines
[
0
].
mid
(
Private
::
mFromPrefixEn
.
length
())
+
'\n'
;
dispText
+=
Private
::
mToPrefix
+
lines
[
1
].
mid
(
Private
::
mToPrefixEn
.
length
())
+
'\n'
;
if
(
n
==
3
)
dispText
+=
Private
::
mCcPrefix
+
lines
[
2
].
mid
(
Private
::
mCcPrefixEn
.
length
())
+
'\n'
;
dispText
+=
Private
::
mDatePrefix
+
lines
[
n
].
mid
(
Private
::
mDatePrefixEn
.
length
())
+
'\n'
;
dispText
+=
Private
::
mSubjectPrefix
+
lines
[
n
+
1
].
mid
(
Private
::
mSubjectPrefixEn
.
length
());
int
i
=
text
.
indexOf
(
Private
::
mSubjectPrefixEn
);
i
=
text
.
indexOf
(
'\n'
,
i
);
if
(
i
>
0
)
dispText
+=
text
.
mid
(
i
);
email
=
true
;
return
dispText
;
}
}
email
=
false
;
return
text
;
}
/******************************************************************************
* Return the text for a text message alarm, in alarm calendar format.
* (The prefix strings are untranslated in the calendar.)
*/
QString
AlarmText
::
toCalendarText
(
const
QString
&
text
)
{
Private
::
setUpTranslations
();
QStringList
lines
=
text
.
split
(
'\n'
,
QString
::
SkipEmptyParts
);
int
maxn
=
lines
.
count
();
if
(
maxn
>=
4
&&
lines
[
0
].
startsWith
(
Private
::
mFromPrefix
)
&&
lines
[
1
].
startsWith
(
Private
::
mToPrefix
))
{
int
n
=
2
;
if
(
lines
[
2
].
startsWith
(
Private
::
mCcPrefix
))
++
n
;
if
(
maxn
>
n
+
1
&&
lines
[
n
].
startsWith
(
Private
::
mDatePrefix
)
&&
lines
[
n
+
1
].
startsWith
(
Private
::
mSubjectPrefix
))
{
// Format the email into a text alarm
QString
calText
;
calText
=
Private
::
mFromPrefixEn
+
lines
[
0
].
mid
(
Private
::
mFromPrefix
.
length
())
+
'\n'
;
calText
+=
Private
::
mToPrefixEn
+
lines
[
1
].
mid
(
Private
::
mToPrefix
.
length
())
+
'\n'
;
if
(
n
==
3
)
calText
+=
Private
::
mCcPrefixEn
+
lines
[
2
].
mid
(
Private
::
mCcPrefix
.
length
())
+
'\n'
;
calText
+=
Private
::
mDatePrefixEn
+
lines
[
n
].
mid
(
Private
::
mDatePrefix
.
length
())
+
'\n'
;
calText
+=
Private
::
mSubjectPrefixEn
+
lines
[
n
+
1
].
mid
(
Private
::
mSubjectPrefix
.
length
());
int
i
=
text
.
indexOf
(
Private
::
mSubjectPrefix
);
i
=
text
.
indexOf
(
'\n'
,
i
);
if
(
i
>
0
)
calText
+=
text
.
mid
(
i
);
return
calText
;
}
}
return
text
;
}
void
AlarmText
::
Private
::
clear
()
{
mType
=
None
;
mBody
.
clear
();
mTo
.
clear
();
mFrom
.
clear
();
mCc
.
clear
();
mTime
.
clear
();
mSubject
.
clear
();
mKMailSerialNum
=
0
;
}
/******************************************************************************
* Set up messages used by executeDropEvent() and emailHeaders().
*/
void
AlarmText
::
Private
::
setUpTranslations
()
{
initialise
();
if
(
mFromPrefix
.
isNull
())
{
mFromPrefix
=
i18nc
(
"@info/plain 'From' email address"
,
"From:"
);
mToPrefix
=
i18nc
(
"@info/plain Email addressee"
,
"To:"
);
mCcPrefix
=
i18nc
(
"@info/plain Copy-to in email headers"
,
"Cc:"
);
mDatePrefix
=
i18nc
(
"@info/plain"
,
"Date:"
);
mSubjectPrefix
=
i18nc
(
"@info/plain Email subject"
,
"Subject:"
);
// Todo prefixes
mTitlePrefix
=
i18nc
(
"@info/plain Todo calendar item's title field"
,
"To-do:"
);
mLocnPrefix
=
i18nc
(
"@info/plain Todo calendar item's location field"
,
"Location:"
);
mDuePrefix
=
i18nc
(
"@info/plain Todo calendar item's due date/time"
,
"Due:"
);
}
}
/******************************************************************************
* Check whether a text is an email.
* Reply = number of email header lines, or 0 if not an email.
*/
int
AlarmText
::
Private
::
emailHeaderCount
(
const
QStringList
&
lines
)
{
setUpTranslations
();
int
maxn
=
lines
.
count
();
if
(
maxn
>=
4
&&
lines
[
0
].
startsWith
(
mFromPrefix
)
&&
lines
[
1
].
startsWith
(
mToPrefix
))
{
int
n
=
2
;
if
(
lines
[
2
].
startsWith
(
mCcPrefix
))
++
n
;
if
(
maxn
>
n
+
1
&&
lines
[
n
].
startsWith
(
mDatePrefix
)
&&
lines
[
n
+
1
].
startsWith
(
mSubjectPrefix
))
return
n
+
2
;
}
return
0
;