#####################################################################
#
#     TCL SMS mini library
#
# by Gerhard Reithofer
# Techn. EDV Reithofer, Technical software solutions
# mailto:gerhard.reithofer@tech-edv.co.at 
# http://www.tech-edv.co.at
#
# See COPYING for further details
#
# This is a part of our self-developed SMS-library, which is also
# a part of our GSM-library for TCL. 
# You may find it on our web server:
#      http://www.tech-edv.co.at/programmierung/gplsw.html
#
# Information mostly retrieved from:
#
#   Developer's Guide:
#    SMS with the SMS PDU-mode
#  Version 1.2 (30.07.97) by Siemens AG
# found at: http://www.min.at/prinz/s25/smspdu.pdf
#
#  ... you will find many, many, many usefult things at the
#      (M)obile (I)nformation (N)etwork
# site by Richard Prinz Richard.Prinz@min.at
#
# ... and NOBI's real great GSM site
#              http://www.nobbi.com/
#

global SMS_FLAG PDU_TYPE SMS_MSG_VALID SMS_MSG_VP_VALUE

##############################################
#
# SMS PDU type byte - DELIVER mode
# 
# Bit 7 - Reply Path 
set PDU_DEF(RP)   0
# Bit 6 - User Data Header Indicator
set PDU_DEF(UDHI) 0
# Bit 5 - Status Report Request
set PDU_DEF(SRR)  0
# Bit 4+3 - Valid Period Flag - no value
set PDU_DEF(VPF)  0
# Bit 2 - Reject Duplicate
set PDU_DEF(RD)  0
# Bit 1+0 - Message Type Indicator (default is SMS-SUBMIT)
set PDU_DEF(MTI)  1
##############################################
#
# SMS FLAGS default - DELIVER mode
#
##############################################
# 
# Specify SMS -> fromphone
set SMS_DEF(SCA) "00"
# Extract PDU flag  later
# set SMS_DEF(PDU) [set_pdu_flags -1]
# Message reference -> 00-FF 
set SMS_DEF(MR) "00"
# Destination address (phone number)
# set SMS_DEF(DA) [phone2pdu $pnum]
# Protocol IDentifier -> PDU has tobe treted as sms
set SMS_DEF(PID) "00"
# Data Coding Scheme -> default 7-bit coding 
set SMS_DEF(DCS) "00"
# Validy Period flag -> no value given (PDU_DEF(VPF) must be 0)
set SMS_DEF(VP) "" 

# debug_var SMS_MSG_VP_VALUE(2)
# debug_out "1 SMS_MSG_VP_VALUE [array names SMS_MSG_VP_VALUE]"

#
# Character map found at:
#     http://www.dreamfabric.com/sms/default_alphabet.html
# Many thanks to the dream team:
#   Joakim Eriksson, Niclas Finne, Lars Olsson, 
#   Lars Petterson, Karl-Petter Åkesson, Erik Klintskog 
#
# list 0 - standad char mapping from GSM 03.38. to ISO-8859-1
# list 1 - char after escape GSM
# list 3 - corr. ISO char 
#
# 0 - means unsupoorted (like greek alphabet, Euro symbol...)
#
proc pdu2iso { str } {
  debug_out "CALL: pdu2iso $str" 3 
  set gsm_default_alphabet [list [list \
    64 163  36 165 232 233 250 236 242 199  10 216 248  13 197 229 \
     0  95   0   0   0   0   0   0   0   0   0   0 198 230 223 202 \
    32  33  34  35   0  37  38  39  40  41  42  43  44  45  46  47 \
    48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63 \
   161  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79 \
    80  81  82  83  84  85  86  87  88  89  90 196 214 209 220 167 \
   191  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 \
   112 113 114 115 116 117 118 119 120 121 122 228 246 241 252 224]\
    [list 10  20  40  41  47  60  61  62  64 101]\
    [list 12  94 123 125  92  91 126  93 124   0]\
  ]
  set notsup " "
  set unknow "?"
  set cmap [lindex $gsm_default_alphabet 0]
  set escp [lindex $gsm_default_alphabet 1]
  set esci [lindex $gsm_default_alphabet 2]
  set rval ""

  set blist {}
  set sl [string length $str]
  for {set i 0} {$i < $sl} {incr i} {
    scan [string index $str $i] "%c" b
    lappend blist $b
  }

  set lc -1
  set cnt 0
  set stl [llength $blist]
  while {$cnt < $stl} {
    set inp [lindex $blist $cnt] ; ### nth character
    set map [lindex $cmap $inp]  ; ### mapped value
    if {$map eq {}} {set map -1}
# puts "inp=$inp"
    switch -- $map {
      -1 { ; ### unknown chacter (not found in cmap) - should never appear!!!
        puts "\007" ; ### HELP!
        append rval $unknow
        debug_out "rval=$rval" 1 
        exit 0
      }
      0 {  ; ### unsupported character
        append rval $notsup
      }
      13 { ; ### CR/LF problem...do nothin under Unix
      }
      27 { ; ### escaped chacter
       set inp [lindex $str [incr cnt]] ; ### fetch next char
       set escidx [lsearch $escp $inp]  ; ### is it a valid escape char?
        if {$escidx == -1} {
          append rval [format "%c" 27]
        } else {
          append rval [lindex $esci $escidx]
        }
      }
      default { ; ### the result directly
        append rval [format "%c" $map]
      }
    }
    set lc $map
    incr cnt
  }
  debug_out "RETURN: pdu2iso $rval" 3 
  return $rval
}

proc set_pdu_flags { val } {
  global PDU_TYPE PDU_DEF
  debug_out "CALL: set_pdu_flags $val" 3 

  if {$val == -1} {
##### SUBMIT mode - MS -> SMSC
    # Bit 7 - Reply Path -> 0
    set PDU_TYPE(RP)   $PDU_DEF(RP)
    # Bit 6 - User Data Header Indicator -> 0
    set PDU_TYPE(UDHI) $PDU_DEF(UDHI)
    # Bit 5 - Status Report Request -> 0
    set PDU_TYPE(SRR)  $PDU_DEF(SRR)
    # Bit 4+3 - Valid Period Flag -> see get_vp_value
    set PDU_TYPE(VPF)  $PDU_DEF(VPF)
    # Bit 2 - Reject Duplicate -> 0
    set PDU_TYPE(RD)   $PDU_DEF(RD)
    # Bit 1+0 - Message Type Indicator - must be "01"
    set PDU_TYPE(MTI)  $PDU_DEF(MTI)
    set val [expr ($PDU_TYPE(RP)  <<7) | \
                  ($PDU_TYPE(UDHI)<<6) | \
                  ($PDU_TYPE(SRR) <<5) | \
                  ($PDU_TYPE(VPF) <<3) | \
                  ($PDU_TYPE(RD)  <<2) | \
                   $PDU_TYPE(MTI)]
# disp_sms_flags
# puts "set_pdu_flag -> $val"
  } else {
##### DELIVER mode SMSC -> MS
    # Bit 7 - Reply Path
    set PDU_TYPE(RP)   [expr ($val & 128) >> 7] 
    # Bit 6 - User Data Header Indicator
    set PDU_TYPE(UDHI) [expr ($val &  64) >> 6]
    # Bit 5 - Statue Report Inidicator
    set PDU_TYPE(SRI)  [expr ($val &  32) >> 5]
    # Bit 4+3 - VPF - should only be of interest at SUBMIT
    set PDU_TYPE(VPF)  [expr ($val &  24) >> 3] 
    # Bit 2 - More Message to Send 
    set PDU_TYPE(MMS)  [expr ($val &   4) >> 2]
    # Bit 1+0 - Message Type Indicator
    set PDU_TYPE(MTI)  [expr $val &   3]
  }

  set rval [format "%02x" $val]

  debug_out "RETURN: set_pdu_flags $rval" 3 
  return $rval
}

proc readc { len } {
  global global_msg
  debug_out "CALL: readc $len" 8 

  set rval [string range $global_msg 0 [expr $len-1]]
  set global_msg  [string range $global_msg $len end]

  debug_out "RETURN: readc '$rval'" 3 
  return $rval
}

############################################
#
# ...the strange pdu stufffffffffffffffffff
#
############################################

proc swap_bytes { num } {
  debug_out "CALL: swap_bytes $num" 3 

  set rval ""
  set len [string length $num]
  for {set i 0} {$i<$len} {incr i 2} {
    append rval "[string index $num [expr $i+1]][string index $num $i]"
  }

  debug_out "RETURN: swap_bytes $rval" 3 
  return $rval
} 

proc get_vp_value { pdu vpf } {
  global SMS_MSG_VP_VALUE SMS_MSG_VALID
debug_out "CALL: get_vp_value $pdu $vpf" 3 

  set SMS_MSG_VALID(NONE)     0
  set SMS_MSG_VALID(RESERVED) 1
  set SMS_MSG_VALID(RELATIVE) 2
  set SMS_MSG_VALID(ABSOLUTE) 3

  set SMS_MSG_VP_VALUE($SMS_MSG_VALID(NONE))     [get_text "none" siemplug]
  set SMS_MSG_VP_VALUE($SMS_MSG_VALID(RESERVED)) "* Error *"
  set SMS_MSG_VP_VALUE($SMS_MSG_VALID(RELATIVE)) \
          [list [get_text "%d minutes" siemplug]\
                [get_text "%d hours"   siemplug]\
                [get_text "%d days"    siemplug]\
                [get_text "%d weeks"   siemplug]]

  set vp ""
  set fmt_str $SMS_MSG_VP_VALUE($vpf)
# debug_out "$SMS_MSG_VALID(RELATIVE) == $vpf => [string_equal $SMS_MSG_VALID(RELATIVE) $vpf]"
        if [string_equal $vpf $SMS_MSG_VALID(NONE)] {
    set vp $fmt_str
  } elseif [string_equal $vpf $SMS_MSG_VALID(RESERVED)] {
    set vp $fmt_str
  } elseif [string_equal $vpf $SMS_MSG_VALID(RELATIVE)] {
    scan $pdu "%x" val
    if {$val <= 143} {
      set vp [format [lindex $fmt_str 0] [expr ($val+1)*5]]
    } elseif { $val <= 167} {
      set vp [format [lindex $fmt_str 1] [expr 12+($val-143)/2]]
    } elseif { $val <= 196} {
      set vp [format [lindex $fmt_str 2] [expr ($val-166)]]
    } else {
      set vp [format [lindex $fmt_str 3] [expr ($val-192)]]
    }
  } elseif [string_equal $vpf $SMS_MSG_VALID(ABSOLUTE)] {
    set vp [format $fmt_str [pdu2time $pdu]]
  } else {
    set vp [get_text "* internal error *" siemplug]
  }
  debug_out "RETURN: get_vp_value $vp" 3 
  return $vp 
}

proc read_vp_value { vpf } {
  debug_out "CALL: read_vp_value" 3 

  switch $vpf {
    0 { ### NO SMS_FLAG(VP) preset
        set vp ""         
    }
    1 { ### reserved - unused - should we call "error"?
        set vp ""         
    } 
    2 { ### "relative" period (integer)
        set vp [readc 2]  
    } 
    3 { ### "absolute" period (timestamp)
        set vp [readc 14] 
    } 
  }

  debug_out "RETURN: read_vp_value $vp" 3 
  return $vp 
}

proc read_pdu_flags { pdu } {
  global SMS_FLAG PDU_TYPE global_msg
  debug_out "CALL: read_pdu_flags" 3 

  if [info exists PDU_TYPE] {unset PDU_TYPE}
  if [info exists SMS_FLAG] {unset SMS_FLAG}

  set global_msg $pdu
# Service Center Adress
  set SMS_FLAG(SCA) [read_pdu_phone 1]

# Protocol Data Unit
  set SMS_FLAG(PDU) [readc 2]
  scan $SMS_FLAG(PDU) "%x" dec
  set_pdu_flags $dec

# disp_sms_flags
# puts "PDU_TYPE(MTI)=$PDU_TYPE(MTI)"
  switch $PDU_TYPE(MTI) {
    0 { 
      ### SMS-DELIVER
      ### Message Reference
      ### We do NOT GET this value but we 
      ### MUST GENERATE it (e.g. 00) in DELIVER mode
# ??? set SMS_FLAG(MR) [readc 2]
      ### Originator Address
      set SMS_FLAG(OA) [read_pdu_phone 0]
      ### Protocol IDentifier
      set SMS_FLAG(PID) [readc 2]
      ### Data Coding Scheme
      set SMS_FLAG(DCS) [readc 2]
      ### SMS Center Time Stamp
      set SMS_FLAG(SCTS) [readc 14]
# puts "DEBUG: $SMS_FLAG(OA) $SMS_FLAG(PID) $SMS_FLAG(DCS) $SMS_FLAG(SCTS)"
    }
    1 {
      ### SMS-SUBMIT
      ### Message Reference
      ### We do NOT GET this value but we 
      ### MUST GENERATE it (e.g. 00) in DELIVER mode
      set SMS_FLAG(MR) [readc 2]
      ### Destination Address 
      set SMS_FLAG(DA) [read_pdu_phone 0]
      ### Protocol IDentifier
      set SMS_FLAG(PID) [readc 2]
      ### Data Coding Scheme
      set SMS_FLAG(DCS) [readc 2]
      ### Validy Period - returned as explaining string it the moment
      set SMS_FLAG(VP) [read_vp_value $PDU_TYPE(VPF)]
# puts "DEBUG: Gültigkeitsdauer: $ValidPeriod"
    }
    2 {
    ### SMS-COMMAND - reserved
      warning "Message type SMS-COMMAND not supportet!"
      return -1
    }
    default {
      warning "Invalid PDU_TYPE flag MTI: $PDU_TYPE(MTI)!"
      return -1
    }
  }

# User Data Length
  set SMS_FLAG(UDL) [readc 2]
  scan $SMS_FLAG(UDL) "%x" len

  debug_out "RETURN: read_pdu_flags $len" 3 
  return $len
}

proc pdu2phone { pdu } {
  debug_out "RETURN: pdu2phone $pdu" 3 

  set toa [string range $pdu 0 1]
  set num [swap_bytes [string range $pdu 2 end]]
  set lch [expr [string length $num]-1]
  set lc [string toupper [string index $num $lch]]
  if {$lc eq "F"} { set num [string range $num 0 [expr $lch-1]] }
  if {$toa == 91} { set num "+$num" }

  debug_out "RETURN: pdu2phone $num" 3 
  return $num
}

proc read_pdu_phone { octets } {
  debug_out "CALL: read_pdu_phone $octets"  3 

  set hex [readc 2]
  scan $hex "%x" len

# if len is number of octets (SCA only)!!!
  if ($octets) {
    set len [expr ($len-1)*2]
  } else {
    if [expr $len%2] { incr len }
  }

# we read 1 byte TOA and the hex digits
  set pdu [readc [expr $len+2]]

  debug_out "RETURN: read_pdu_phone $pdu"  3 
  return $pdu
}

proc pdu2time { timestamp } {
  debug_out "CALL: pdu2time $timestamp" 3 

  set dtz [swap_bytes $timestamp]
  set date "20[string range $dtz 0 1]"
  append date ".[string range $dtz 2 3].[string range $dtz 4 5]"
  set time "[string range $dtz 6 7]"
  append time ":[string range $dtz 8 9]:[string range $dtz 10 11]"
# Let's remove leading zeroes to avoid "Invalid octal number 08"...
  set zdata [string range $dtz 12 end]
  regsub ^0+(.+) $zdata \\1 znum
  set zone [expr $znum/4]
  if {$zone > 12} {
    set res [list $date $time "-[expr 24-$zone]h" ]
  } else {
    set res [list $date $time [format "+%dh" $zone]]
  }

  debug_out "RETURN: pdu2time $res" 3 
  return $res
}

proc phone2pdu { num } {
  debug_out "CALL: phone2pdu $num" 3 
# bit length byte
#  7   - always 1
#  6-4 - type of number: 001 (international) or 000 (unknown)
#  3-0 - NPI: 0000
# -> 0x91 for international
#    0x81 for unknown (national) numbers
# bugs : no valid digit checking is done (apeces, chars...)
#
  if {"+" eq [string index $num 0]} {
    set toa "91"
    set num [string range $num 1 end]
  } else {
    set toa "81"
  }

  set lnu [string length $num]

# if length is odd, then we append a "F"
  if [expr $lnu%2] { append num "F" }

  set res ""
  set len [string length $num]
  for {set i 1} {$i < $len} {set i [expr $i+2]} {
    append res [string index $num       $i   ]
    append res [string index $num [expr $i-1]]
  }

  set rval [format "%02X%s%s" $lnu $toa $res]

  debug_out "RETURN: phone2pdu $rval" 3 
  return $rval
}

proc debug_bin { n b1 b2 } {
# debug_out "debug_bin $n $b1 $b2" 6
  if {$b1<=255} {
    binary scan [format %c $b1] B* bits1 
    set hex1 [format %02x $b1]
  } else {
    binary scan [format %c [expr  $b1 &   255    ]] B* r1 
    binary scan [format %c [expr ($b1 & 65280)>>8]] B* r2
    set bits1 "$r2 $r1"
    set hex1 [format %04x $b1]
  }
  if {$b2<=255} {
    binary scan [format %c $b2] B* bits2 
    set hex2 [format %02x $b2]
  } else {
    binary scan [format %c [expr  $b2 &  255     ]] B* r1 
    binary scan [format %c [expr ($b2 & 65280)>>8]] B* r2
    set bits2 "$r2 $r1"
    set hex2 [format %04x $b2]
  }
# puts "$n '$bits1' '$bits2' $hex1 $hex2 $b1 $b2"
}

### Convert packed 7-bit data to a list of single bytes (in decimal)
proc unpack_pdu { msg udl } {
  debug_out "CALL: unpack_pdu $msg $udl" 5

  set outstr ""
  set revbyte {}
# bit masks         0   1   2   3   4   5   6
  set nmask [list 127  63  31  15   7   3   1]
  set omask [list 128 192 224 240 248 252 254]

### Let's convert the hex codes into a list of bytes
  set lmsg [string length $msg]
  for {set i 0} {$i < $lmsg} {incr i 2} { 
    set buffi [string range $msg $i [expr $i+1]]
    scan $buffi "%x" dec
    lappend revbyte $dec
  }
  set i 0
  set buffo [lindex $revbyte $i]
  set out [expr $buffo & [lindex $nmask $i]]
  incr i
  while {[llength $out]<$udl} {
    set lsh [expr $i%7]
    set rsh [expr 8-$lsh]
    set buffn [lindex $revbyte $i]

    set byteo [expr $buffo & [lindex $omask $lsh]]
    set byten [expr $buffn & [lindex $nmask $lsh]]
    set bitso [expr $byteo>>$rsh]
    set bitsn [expr $byten<<$lsh]
    set outch [expr $bitso|$bitsn]
    lappend out $outch

    if [expr {$lsh == 6} && {[llength $out]<$udl}] {
      lappend out [expr ($buffn & [lindex $omask $lsh]) >> 1]
    } 

    set buffo $buffn
    incr i
  }

  debug_out "RETURN: unpack_pdu $out" 5
  return $out
}

proc pdu2txt { msg udl } {
### now we convert the integer list to pdu chars...
  debug_out "CALL: pdu2txt $msg $udl" 5

  set out [unpack_pdu $msg $udl]
  set str ""
  foreach b $out { append str [format "%c" $b] }
  set outstr [pdu2iso $str]

  debug_out "RETURN: pdu2txt $outstr" 5 
  return $outstr

}

proc sms_message2txt { pdu } {
  global SMS_FLAG PDU_TYPE
  debug_out "CALL: sms_message2txt $pdu" 3 

  set msglen [read_pdu_flags $pdu] ; ### sets also $global_msg 
  set txt [pdu2txt $global_msg $msglen]

  debug_out "RETURN: sms_message2txt $txt" 3 
  return $txt
}

##################################################################
#
#  Here go the common ObexTool functions ... the following code
#  is NOT part of out GSM-library
#
##################################################################

##################################################################
#
#  BEGIN - Namespace variable declarations 
#
  variable version 0.3
  variable dlg_title \
    "ObexTool SMS-Plugin $version - (c) Gerhard Reithofer 2003-05"
  variable pathname ""
  variable top_level .sms
  variable label_width 24
  variable header_data ""
  variable dialog_font {Helvetica 10}
  variable label_font {Helvetica 10 bold}
  variable window_font {fixed 12}
  variable window_width  60
  variable window_height 20
  variable magic_siemens "0b0b"
  variable sms_hex_len 350
	variable main_frame
#
#   END  - Namespace variable declarations 
#
##################################################################

proc label_entry { name elabel dval } {
  variable label_font
  variable dialog_font
  variable label_width
  debug_out "label_entry $name $elabel $dval" 5
	LabelEntry $name -label $elabel -labelwidth $label_width \
									 -labelfont $label_font -justify left \
                   -text $dval -entrybg white -font $dialog_font
  pack $name -expand 1 -fill x
}

proc save_message { } {
  variable pathname
  variable top_level 
	variable main_frame
  debug_out "save_message" 5

  set name [file tail [file rootname $pathname]]
  set sl [string length $name]
  set nname ""
  for {set i 0} {$i<$sl} {incr i} {
    set c [string index $name $i]
    if {[string is wordchar $c]||$c eq "."||$c eq "-"} {
      append nname $c
    } else {
      append nname _
    }
  }
  set oname [save_filename $nname.txt txt]
  if [string_empty $oname] return
  set header {}
  set smstxt {}
	set smslbl ""
  set wlist [winfo children $main_frame]
  foreach win $wlist {
    set class [winfo class $win]
debug_out "$class: $win" 6
    switch $class {
      LabelEntry {
        set title [$win cget -label]
				set value [$win cget -text]
        lappend header "$title $value"
      }
      LabelFrame {
				set smslbl [$win cget -text]
			}
      Text {
        set smstxt [$win get 0.0 end]
      }
      default {
        set msg [get_text "Unexpected window class '%s'!" siemplug]
        internal_error [format $msg $class]
      }
    }
  }
  lappend header "$smslbl\n$smstxt"
  set fd [open $oname "w"]
  foreach line $header { puts $fd $line }
  close $fd
  destroy $top_level
  status_msg [format [get_text "SMS message saved as '%s'!" siemplug] $oname]
}

proc sms_dialog { title sms_text } {
  variable top_level
  variable label_font
  variable label_width
  variable window_width
  variable window_height
  variable window_font
	variable main_frame
  variable dlg_title 

  set buttons [list [get_text "&Save" siemplug] \
		                  [get_text "Write SMS text into file"] \
		                 	"[namespace current]::save_message"\
                    [get_text "&Close" siemplug] \
										  [get_text "Close SMS window"] \
											"after idle {destroy $top_level}"]
  set main_frame [new_window $top_level $dlg_title $title $buttons 1 .]

### Add incoming/outgoing specific flag data (see sm?_* plugin files)
  add_flag_data $main_frame

### Add SMS text window frame
  set lf [LabelFrame $main_frame.lbl -font $label_font\
	         -justify left -text [get_text "SMS text:"]]
  pack $lf -expand 1 -fill x 
  set tw [text $main_frame.txt -font $window_font -wrap word\
	         -width $window_width -height $window_height]
  pack $tw -expand 1 -fill x 
debug_var tw 7
  $tw insert end $sms_text

	BWidget::place $top_level 0 0 center .
	wm deiconify $top_level
}

proc read_file { path binary } {
  debug_out "read_file $path" 5
  set local [ObexFile::read_file_tmp $path]
  if [string_empty $local] { return {} }
  set fd [open $local "r"]
  if $binary {fconfigure $fd -translation binary}
  set res [read $fd]
  close $fd
  file delete $local
  return $res
}

proc init_plugin { smsfile } {
  debug_out "init_plugin $smsfile" 5
  global PDU_TYPE SMS_FLAG global_msg
  variable top_level
  variable header_data
  variable model_params
  variable pathname $smsfile
  variable magic_siemens
  variable sms_hex_len
###
### Is a SMS window already open?
###
  if [winfo exists $top_level] {
     set msg [get_text "SMS data window already open!" siemplug]
     append msg \
       [get_text "\nPlease close it before opening a new one." siemplug]
     warning $msg
     return -1
  }

###
### Read SMS file
###
  set bin [read_file $smsfile 1]
  if [string_empty $bin] {
    set msg [get_text "Unable to download file '%s' or file is empty!" siemplug]
    warning [format $smsfile $smsfile]
    return -1"
  }
  set res [binary scan $bin H* sms]
debug_out "sms_slen=[string length $sms] -> [string range $sms 0 3]"
  if ![string_equal [string range $sms 0 3] $magic_siemens] {
    set msg [get_text "No Siemens SMS file signature found!" siemplug]
    append msg [get_text "\nUnable to display SMS text." siemplug]
    warning $msg
    return -1
  }

### The 1st $header_max bytes are (currently unused) header data!?!?!?
### The sms message part is always 175 bytes, whereas the data beyond
### the used data may be filled with 0xff.
### Many thanks to Hendrik Sattler <sattler2000@gmx.de>, the creator
### of SCMxx (http://www.hendrik-sattler.de/scmxx/) for his help and hints.
  set header_len [expr [string length $sms] - $sms_hex_len]
  set pdu_data [string range $sms $header_len end]
  set header_data [string range $sms 0 [incr header_len -1]] 
###
### Interprete the pdu header - this sets also $global_msg 
###
  set msglen [read_pdu_flags $pdu_data]
  return $msglen
}
