diff --git a/res/drawable-hdpi/ic_call_made_grey600_24dp.png b/res/drawable-hdpi/ic_call_made_grey600_24dp.png
new file mode 100644
index 0000000000..7d0807b0bf
Binary files /dev/null and b/res/drawable-hdpi/ic_call_made_grey600_24dp.png differ
diff --git a/res/drawable-hdpi/ic_call_missed_grey600_24dp.png b/res/drawable-hdpi/ic_call_missed_grey600_24dp.png
new file mode 100644
index 0000000000..0241747c68
Binary files /dev/null and b/res/drawable-hdpi/ic_call_missed_grey600_24dp.png differ
diff --git a/res/drawable-hdpi/ic_call_received_grey600_24dp.png b/res/drawable-hdpi/ic_call_received_grey600_24dp.png
new file mode 100644
index 0000000000..5c9a88d126
Binary files /dev/null and b/res/drawable-hdpi/ic_call_received_grey600_24dp.png differ
diff --git a/res/drawable-mdpi/ic_call_made_grey600_24dp.png b/res/drawable-mdpi/ic_call_made_grey600_24dp.png
new file mode 100644
index 0000000000..f275722ffe
Binary files /dev/null and b/res/drawable-mdpi/ic_call_made_grey600_24dp.png differ
diff --git a/res/drawable-mdpi/ic_call_missed_grey600_24dp.png b/res/drawable-mdpi/ic_call_missed_grey600_24dp.png
new file mode 100644
index 0000000000..609ef52617
Binary files /dev/null and b/res/drawable-mdpi/ic_call_missed_grey600_24dp.png differ
diff --git a/res/drawable-mdpi/ic_call_received_grey600_24dp.png b/res/drawable-mdpi/ic_call_received_grey600_24dp.png
new file mode 100644
index 0000000000..685982d8e2
Binary files /dev/null and b/res/drawable-mdpi/ic_call_received_grey600_24dp.png differ
diff --git a/res/drawable-xhdpi/ic_call_made_grey600_24dp.png b/res/drawable-xhdpi/ic_call_made_grey600_24dp.png
new file mode 100644
index 0000000000..1e609bb5e6
Binary files /dev/null and b/res/drawable-xhdpi/ic_call_made_grey600_24dp.png differ
diff --git a/res/drawable-xhdpi/ic_call_missed_grey600_24dp.png b/res/drawable-xhdpi/ic_call_missed_grey600_24dp.png
new file mode 100644
index 0000000000..fb5e2794f0
Binary files /dev/null and b/res/drawable-xhdpi/ic_call_missed_grey600_24dp.png differ
diff --git a/res/drawable-xhdpi/ic_call_received_grey600_24dp.png b/res/drawable-xhdpi/ic_call_received_grey600_24dp.png
new file mode 100644
index 0000000000..91b5587a8a
Binary files /dev/null and b/res/drawable-xhdpi/ic_call_received_grey600_24dp.png differ
diff --git a/res/drawable-xxhdpi/ic_call_made_grey600_24dp.png b/res/drawable-xxhdpi/ic_call_made_grey600_24dp.png
new file mode 100644
index 0000000000..66a9ff46e8
Binary files /dev/null and b/res/drawable-xxhdpi/ic_call_made_grey600_24dp.png differ
diff --git a/res/drawable-xxhdpi/ic_call_missed_grey600_24dp.png b/res/drawable-xxhdpi/ic_call_missed_grey600_24dp.png
new file mode 100644
index 0000000000..84c13861cb
Binary files /dev/null and b/res/drawable-xxhdpi/ic_call_missed_grey600_24dp.png differ
diff --git a/res/drawable-xxhdpi/ic_call_received_grey600_24dp.png b/res/drawable-xxhdpi/ic_call_received_grey600_24dp.png
new file mode 100644
index 0000000000..f4be04c671
Binary files /dev/null and b/res/drawable-xxhdpi/ic_call_received_grey600_24dp.png differ
diff --git a/res/layout/conversation_item_update.xml b/res/layout/conversation_item_update.xml
index a3c927e65b..29557e17a1 100644
--- a/res/layout/conversation_item_update.xml
+++ b/res/layout/conversation_item_update.xml
@@ -1,21 +1,25 @@
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/conversation_update_item"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center"
+ android:padding="20dp">
-
+
+
-
-
+ android:textColor="?attr/conversation_group_member_name"
+ tools:text="Sasha called you"/>
+
+
+
diff --git a/src/org/thoughtcrime/redphone/RedPhoneService.java b/src/org/thoughtcrime/redphone/RedPhoneService.java
index 7a8a3cb5a4..90732766dd 100644
--- a/src/org/thoughtcrime/redphone/RedPhoneService.java
+++ b/src/org/thoughtcrime/redphone/RedPhoneService.java
@@ -48,6 +48,7 @@ import org.thoughtcrime.redphone.signaling.SignalingSocket;
import org.thoughtcrime.redphone.ui.NotificationBarManager;
import org.thoughtcrime.redphone.util.Base64;
import org.thoughtcrime.redphone.util.UncaughtExceptionHandlerManager;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -92,15 +93,12 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
private int state;
private byte[] zid;
-// private String localNumber;
private String remoteNumber;
-// private String password;
private CallManager currentCallManager;
private LockManager lockManager;
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
private Handler handler;
-// private CallLogger.CallRecord currentCallRecord;
private IncomingPstnCallListener pstnCallListener;
@Override
@@ -163,17 +161,9 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
registerReceiver(pstnCallListener, new IntentFilter("android.intent.action.PHONE_STATE"));
}
-// private void initializeApplicationContext() {
-// ApplicationContext context = ApplicationContext.getInstance();
-// context.setContext(this);
-// context.setCallStateListener(this);
-// }
-
private void initializeResources() {
this.state = RedPhone.STATE_IDLE;
this.zid = getZID();
-// this.localNumber = TextSecurePreferences.getLocalNumber(this);
-// this.password = TextSecurePreferences.getPushServerPassword(this);
this.lockManager = new LockManager(this);
}
@@ -216,8 +206,8 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
this.currentCallManager.start();
NotificationBarManager.setCallInProgress(this);
-//
-// currentCallRecord = CallLogger.logOutgoingCall(this, remoteNumber);
+ DatabaseFactory.getSmsDatabase(this).insertOutgoingCall(remoteNumber);
+
}
private void handleBusyCall(Intent intent) {
@@ -246,14 +236,14 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
}
private void handleMissedCall(String remoteNumber) {
-// CallLogger.logMissedCall(this, remoteNumber, System.currentTimeMillis());
+ DatabaseFactory.getSmsDatabase(this).insertMissedCall(remoteNumber);
NotificationBarManager.notifyMissedCall(this, remoteNumber);
}
private void handleAnswerCall(Intent intent) {
state = RedPhone.STATE_ANSWERING;
incomingRinger.stop();
-// currentCallRecord = CallLogger.logIncomingCall(this, remoteNumber);
+ DatabaseFactory.getSmsDatabase(this).insertReceivedCall(remoteNumber);
if (currentCallManager != null) {
((ResponderCallManager)this.currentCallManager).answer(true);
}
@@ -262,7 +252,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
private void handleDenyCall(Intent intent) {
state = RedPhone.STATE_IDLE;
incomingRinger.stop();
-// CallLogger.logMissedCall(this, remoteNumber, System.currentTimeMillis());
+ DatabaseFactory.getSmsDatabase(this).insertMissedCall(remoteNumber);
if(currentCallManager != null) {
((ResponderCallManager)this.currentCallManager).answer(false);
}
diff --git a/src/org/thoughtcrime/redphone/ui/NotificationBarManager.java b/src/org/thoughtcrime/redphone/ui/NotificationBarManager.java
index 675f60fa6f..47c2c4d19a 100644
--- a/src/org/thoughtcrime/redphone/ui/NotificationBarManager.java
+++ b/src/org/thoughtcrime/redphone/ui/NotificationBarManager.java
@@ -22,9 +22,15 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
+import android.support.v4.app.NotificationCompat;
import org.thoughtcrime.redphone.RedPhone;
+import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.recipients.RecipientFactory;
+import org.thoughtcrime.securesms.recipients.Recipients;
/**
* Manages the state of the RedPhone items in the Android notification bar.
@@ -35,7 +41,8 @@ import org.thoughtcrime.securesms.R;
public class NotificationBarManager {
- private static final int RED_PHONE_NOTIFICATION = 313388;
+ private static final int RED_PHONE_NOTIFICATION = 313388;
+ private static final int MISSED_CALL_NOTIFICATION = 313389;
public static void setCallEnded(Context context) {
NotificationManager notificationManager = (NotificationManager)context
@@ -61,26 +68,27 @@ public class NotificationBarManager {
}
public static void notifyMissedCall(Context context, String remoteNumber) {
-// Intent intent = new Intent(DialerActivity.CALL_LOG_ACTION, null,
-// context, DialerActivity.class);
-// PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent, 0);
-// PersonInfo remoteInfo = PersonInfo.getInstance(context, remoteNumber);
+ Intent intent = new Intent(context, ConversationActivity.class);
+ Recipients notifyRecipients = RecipientFactory.getRecipientsFromString(context, remoteNumber, false);
+ intent.putExtra("recipients", notifyRecipients.getIds());
+ intent.putExtra("thread_id", DatabaseFactory.getThreadDatabase(context).getThreadIdFor(notifyRecipients));
+ intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
-// NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
-// builder.setSmallIcon(R.drawable.stat_notify_missed_call);
-// builder.setWhen(System.currentTimeMillis());
-// builder.setTicker(context
-// .getString(R.string.NotificationBarManager_missed_redphone_call_from_s,
-// remoteInfo.getName()));
-// builder.setContentTitle(context.getString(R.string.NotificationBarManager_missed_redphone_call));
-// builder.setContentText(remoteInfo.getName());
-// builder.setContentIntent(launchIntent);
-// builder.setDefaults(Notification.DEFAULT_VIBRATE);
-// builder.setAutoCancel(true);
-//
-// NotificationManager manager = (NotificationManager)context
-// .getSystemService(Context.NOTIFICATION_SERVICE);
-//
-// manager.notify(DialerActivity.MISSED_CALL, builder.build());
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ builder.setSmallIcon(R.drawable.ic_call_missed_grey600_24dp);
+ builder.setWhen(System.currentTimeMillis());
+ builder.setTicker(String.format("Missed call from %s", notifyRecipients.toShortString()));
+ builder.setContentTitle("Missed Signal call");
+ builder.setContentText(String.format("Missed call from %s", notifyRecipients.toShortString()));
+ builder.setContentIntent(pendingIntent);
+ builder.setDefaults(Notification.DEFAULT_VIBRATE);
+ builder.setAutoCancel(true);
+
+ NotificationManager manager = (NotificationManager)context
+ .getSystemService(Context.NOTIFICATION_SERVICE);
+
+ manager.notify(MISSED_CALL_NOTIFICATION, builder.build());
}
}
diff --git a/src/org/thoughtcrime/securesms/ConversationAdapter.java b/src/org/thoughtcrime/securesms/ConversationAdapter.java
index ed636731e8..370cfc723d 100644
--- a/src/org/thoughtcrime/securesms/ConversationAdapter.java
+++ b/src/org/thoughtcrime/securesms/ConversationAdapter.java
@@ -164,9 +164,9 @@ public class ConversationAdapter
String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
MessageRecord messageRecord = getMessageRecord(id, cursor, type);
- if (messageRecord.isGroupAction()) return MESSAGE_TYPE_UPDATE;
- else if (messageRecord.isOutgoing()) return MESSAGE_TYPE_OUTGOING;
- else return MESSAGE_TYPE_INCOMING;
+ if (messageRecord.isGroupAction() || messageRecord.isCallLog()) return MESSAGE_TYPE_UPDATE;
+ else if (messageRecord.isOutgoing()) return MESSAGE_TYPE_OUTGOING;
+ else return MESSAGE_TYPE_INCOMING;
}
private MessageRecord getMessageRecord(long messageId, Cursor cursor, String type) {
diff --git a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
index a8322aa188..b41d36b5c8 100644
--- a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
@@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
+import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.Util;
@@ -26,8 +27,10 @@ public class ConversationUpdateItem extends LinearLayout
private ImageView icon;
private TextView body;
+ private TextView date;
private Recipient sender;
private MessageRecord messageRecord;
+ private Locale locale;
public ConversationUpdateItem(Context context) {
super(context);
@@ -43,6 +46,7 @@ public class ConversationUpdateItem extends LinearLayout
this.icon = (ImageView)findViewById(R.id.conversation_update_icon);
this.body = (TextView)findViewById(R.id.conversation_update_body);
+ this.date = (TextView)findViewById(R.id.conversation_update_date);
setOnClickListener(this);
}
@@ -54,28 +58,45 @@ public class ConversationUpdateItem extends LinearLayout
@NonNull Set batchSelected,
boolean groupThread, boolean pushDestination)
{
- bind(messageRecord);
+ bind(messageRecord, locale);
}
- private void bind(@NonNull MessageRecord messageRecord) {
+ private void bind(@NonNull MessageRecord messageRecord, @NonNull Locale locale) {
this.messageRecord = messageRecord;
this.sender = messageRecord.getIndividualRecipient();
+ this.locale = locale;
this.sender.addListener(this);
- if (messageRecord.isGroupAction()) {
- icon.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_group_grey600_24dp));
+ if (messageRecord.isGroupAction()) setGroupRecord(messageRecord);
+ else if (messageRecord.isCallLog()) setCallRecord(messageRecord);
+ else throw new AssertionError("Neither group no log.");
+ }
- if (messageRecord.isGroupQuit() && messageRecord.isOutgoing()) {
- body.setText(R.string.MessageRecord_left_group);
- } else if (messageRecord.isGroupQuit()) {
- body.setText(getContext().getString(R.string.ConversationItem_group_action_left, sender.toShortString()));
- } else {
- GroupUtil.GroupDescription description = GroupUtil.getDescription(getContext(), messageRecord.getBody().getBody());
- description.addListener(this);
- body.setText(description.toString());
- }
+ private void setCallRecord(MessageRecord messageRecord) {
+ if (messageRecord.isIncomingCall()) icon.setImageResource(R.drawable.ic_call_received_grey600_24dp);
+ else if (messageRecord.isOutgoingCall()) icon.setImageResource(R.drawable.ic_call_made_grey600_24dp);
+ else icon.setImageResource(R.drawable.ic_call_missed_grey600_24dp);
+
+ body.setText(messageRecord.getDisplayBody());
+ date.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, messageRecord.getDateReceived()));
+ date.setVisibility(View.VISIBLE);
+ }
+
+ private void setGroupRecord(MessageRecord messageRecord) {
+ icon.setImageResource(R.drawable.ic_group_grey600_24dp);
+
+ if (messageRecord.isGroupQuit() && messageRecord.isOutgoing()) {
+ body.setText(R.string.MessageRecord_left_group);
+ } else if (messageRecord.isGroupQuit()) {
+ body.setText(getContext().getString(R.string.ConversationItem_group_action_left, sender.toShortString()));
+ } else {
+ GroupUtil.GroupDescription description = GroupUtil.getDescription(getContext(), messageRecord.getBody().getBody());
+ description.addListener(this);
+ body.setText(description.toString());
}
+
+ date.setVisibility(View.GONE);
}
@Override
@@ -88,7 +109,7 @@ public class ConversationUpdateItem extends LinearLayout
Util.runOnMain(new Runnable() {
@Override
public void run() {
- bind(messageRecord);
+ bind(messageRecord, locale);
}
});
}
diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
index 9eaceb0bac..fcb24c6660 100644
--- a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
+++ b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
@@ -19,6 +19,10 @@ public interface MmsSmsColumns {
// Base Types
protected static final long BASE_TYPE_MASK = 0x1F;
+ protected static final long INCOMING_CALL_TYPE = 1;
+ protected static final long OUTGOING_CALL_TYPE = 2;
+ protected static final long MISSED_CALL_TYPE = 3;
+
protected static final long BASE_INBOX_TYPE = 20;
protected static final long BASE_OUTBOX_TYPE = 21;
protected static final long BASE_SENDING_TYPE = 22;
@@ -150,6 +154,22 @@ public interface MmsSmsColumns {
return (type & KEY_EXCHANGE_IDENTITY_UPDATE_BIT) != 0;
}
+ public static boolean isCallLog(long type) {
+ return type == INCOMING_CALL_TYPE || type == OUTGOING_CALL_TYPE || type == MISSED_CALL_TYPE;
+ }
+
+ public static boolean isIncomingCall(long type) {
+ return type == INCOMING_CALL_TYPE;
+ }
+
+ public static boolean isOutgoingCall(long type) {
+ return type == OUTGOING_CALL_TYPE;
+ }
+
+ public static boolean isMissedCall(long type) {
+ return type == MISSED_CALL_TYPE;
+ }
+
public static boolean isGroupUpdate(long type) {
return (type & GROUP_UPDATE_BIT) != 0;
}
diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
index a5d4175859..784d09655f 100644
--- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
@@ -22,6 +22,7 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
+import android.support.annotation.NonNull;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
@@ -343,6 +344,45 @@ public class SmsDatabase extends MessagingDatabase {
return new Pair<>(newMessageId, record.getThreadId());
}
+ public @NonNull Pair insertReceivedCall(@NonNull String number) {
+ return insertCallLog(number, Types.INCOMING_CALL_TYPE, false);
+ }
+
+ public @NonNull Pair insertOutgoingCall(@NonNull String number) {
+ return insertCallLog(number, Types.OUTGOING_CALL_TYPE, false);
+ }
+
+ public @NonNull Pair insertMissedCall(@NonNull String number) {
+ return insertCallLog(number, Types.MISSED_CALL_TYPE, true);
+ }
+
+ private @NonNull Pair insertCallLog(@NonNull String number, long type, boolean unread) {
+ Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, true);
+ long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
+
+ ContentValues values = new ContentValues(6);
+ values.put(ADDRESS, number);
+ values.put(ADDRESS_DEVICE_ID, 1);
+ values.put(DATE_RECEIVED, System.currentTimeMillis());
+ values.put(DATE_SENT, System.currentTimeMillis());
+ values.put(READ, unread ? 0 : 1);
+ values.put(TYPE, type);
+ values.put(THREAD_ID, threadId);
+
+ SQLiteDatabase db = databaseHelper.getWritableDatabase();
+ long messageId = db.insert(TABLE_NAME, null, values);
+
+ DatabaseFactory.getThreadDatabase(context).update(threadId);
+ notifyConversationListeners(threadId);
+ jobManager.add(new TrimThreadJob(context, threadId));
+
+ if (unread) {
+ DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
+ }
+
+ return new Pair<>(messageId, threadId);
+ }
+
protected Pair insertMessageInbox(IncomingTextMessage message, long type) {
if (message.isPreKeyBundle()) {
type |= Types.KEY_EXCHANGE_BIT | Types.KEY_EXCHANGE_BUNDLE_BIT;
diff --git a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
index 3c0bc3ed44..67c13ff8a4 100644
--- a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
@@ -95,6 +95,22 @@ public abstract class DisplayRecord {
return isGroupUpdate() || isGroupQuit();
}
+ public boolean isCallLog() {
+ return SmsDatabase.Types.isCallLog(type);
+ }
+
+ public boolean isIncomingCall() {
+ return SmsDatabase.Types.isIncomingCall(type);
+ }
+
+ public boolean isOutgoingCall() {
+ return SmsDatabase.Types.isOutgoingCall(type);
+ }
+
+ public boolean isMissedCall() {
+ return SmsDatabase.Types.isMissedCall(type);
+ }
+
public static class Body {
private final String body;
private final boolean plaintext;
diff --git a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
index c58a7ab870..e1f9afa7d2 100644
--- a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
@@ -115,6 +115,12 @@ public abstract class MessageRecord extends DisplayRecord {
return emphasisAdded(context.getString(R.string.MessageRecord_left_group));
} else if (isGroupQuit()) {
return emphasisAdded(context.getString(R.string.ConversationItem_group_action_left, getIndividualRecipient().toShortString()));
+ } else if (isIncomingCall()) {
+ return emphasisAdded(String.format("%s called you", getIndividualRecipient().toShortString()));
+ } else if (isOutgoingCall()) {
+ return emphasisAdded(String.format("Called %s", getIndividualRecipient().toShortString()));
+ } else if (isMissedCall()) {
+ return emphasisAdded(String.format("Missed call from %s", getIndividualRecipient().toShortString()));
} else if (getBody().getBody().length() > MAX_DISPLAY_LENGTH) {
return new SpannableString(getBody().getBody().substring(0, MAX_DISPLAY_LENGTH));
}