Skip to main content

SMS Character Counting

The character counter and preview are server-rendered by Sms\renderStatusline() in jethro-sms/src/sms_statusline.php and streamed to the browser via Datastar SSE (?call=sms_statusline). See SMS Datastar / HATEOAS statusline. The segment/cost maths below is the spec for that PHP port (unit-tested in jethro-sms/tests/statusline/). Only the instant text.length character count remains client-side (a Datastar data-text signal).

GSM 03.38 Alphabet

Standard SMS uses the GSM 03.38 7-bit alphabet. Most Latin characters, numbers, and common punctuation are single characters.

GSM Segment Sizes

TypeSingle messageConcatenated
GSM 7-bit160 chars153 chars per segment

Extended GSM Characters

Some characters count as two GSM characters: ^, {, }, [, ], ~, |, .

UCS-2 (Unicode)

When the message contains any non-GSM character, the entire message switches to UCS-2 (UTF-16) encoding:

TypeSingle messageConcatenated
UCS-270 chars67 chars per segment

Unicode Modes

Controlled by SMS_UNICODE_PERMITTED (default: 'when_free'):

ValueBehavior
'when_free' (default)Allowed for single-segment messages (≤70 chars), blocked for longer
'0' (disabled)Non-GSM chars block the Send button entirely
'1' (enabled)Everything allowed; warning shown if removing special chars would save segments

Cost Calculation

If SMS_SEGMENT_COST is configured, the counter multiplies segments × cost and displays the estimated total.

Balance Enforcement

If SMS_BALANCE_ENFORCED is on, the counter checks the estimated cost against the account balance and blocks sending if insufficient.

Display

The #sms-statusline element shows (composed in this order, parts skipped when not applicable):

  • Max-length warning (from raw text)
  • Cost / segment line (from preview when available, raw-text estimate otherwise)
  • — or, when over budget — balance warning that replaces the cost line
  • Unicode cost-doubling warning (from raw text)
  • Test-mode notice

Special case: when the message is unicode-blocked by SMS_UNICODE_PERMITTED policy, only the block warning is shown.

Architecture

The maths (gsmLength, gsmSegmentCount, ucs2SegmentCount, getNonGsmChars, shortenUrlsInText) and the two HTML renderers (renderStatusline, renderPreviewPanel) live in jethro-sms/src/sms_statusline.php as pure, unit-tested functions. Call_SMS_Statusline runs them with a SmsStatuslineConfig snapshot and streams the result. The client posts the form on debounced input and morphs the returned #sms-statusline* / #sms-preview-panel* elements by id. There is one source of truth (the server), eliminating the old two-writer race entirely. See SMS Datastar / HATEOAS statusline.

See Also