1# Device::Gsm::Charset - GSM0338 <=> ASCII charset conversion module 2# Copyright (C) 2004-2015 Cosimo Streppone, cosimo@cpan.org 3# 4# This program is free software; you can redistribute it and/or modify 5# it only under the terms of Perl itself. 6# 7# This program is distributed in the hope that it will be useful, 8# but WITHOUT ANY WARRANTY; without even the implied warranty of 9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10# Perl licensing terms for details. 11 12package Device::Gsm::Charset; 13$VERSION = $Device::Gsm::VERSION; 14 15use strict; 16use constant NPC7 => 0x3F; 17use constant NPC8 => 0x3F; 18use constant ESCAPE => 0x1B; 19 20# The following is the GSM 3.38 standard charset, as shown 21# on some Siemens documentation found on the internet 22 23#my $gsm_charset = join('', 24# '@�$�������'."\n".'��'."\r".'���', # 16 25# '�������������', 26# ' !"# %&�()*+,-./', 27# '0123456789:;<=>?', 28# '-ABCDEFGHIJKLMNO', 29# 'PQRSTUVWXYZ�ֻܻ', 30# '�abcdefghijklmno', 31# 'pqrstuvwxyz�����' 32#); 33 34# 35# These conversion tables are taken from pduconv 0.1 library 36# by Mats Engstrom <mats at nerdlabs dot org>. See also: 37# http://www.mikrocontroller.net/attachment/104082/pduconv.c 38# and 39# https://github.com/rdmeneze/SMSBox-PIC/tree/master/source/pdu_conv 40# 41# Un grazie a Stefano! 42# 43 44@Device::Gsm::Charset::GSM0338_TO_ISO8859 = ( 45 64, # 0 @ COMMERCIAL AT */ 46 163, # 1 � POUND SIGN */ 47 36, # 2 $ DOLLAR SIGN */ 48 165, # 3 � YEN SIGN */ 49 232, # 4 � LATIN SMALL LETTER E WITH GRAVE */ 50 233, # 5 � LATIN SMALL LETTER E WITH ACUTE */ 51 249, # 6 � LATIN SMALL LETTER U WITH GRAVE */ 52 236, # 7 � LATIN SMALL LETTER I WITH GRAVE */ 53 242, # 8 � LATIN SMALL LETTER O WITH GRAVE */ 54 199, # 9 � LATIN CAPITAL LETTER C WITH CEDILLA */ 55 10, # 10 LINE FEED */ 56 216, # 11 � LATIN CAPITAL LETTER O WITH STROKE */ 57 248, # 12 � LATIN SMALL LETTER O WITH STROKE */ 58 13, # 13 CARRIAGE RETURN */ 59 197, # 14 � LATIN CAPITAL LETTER A WITH RING ABOVE */ 60 229, # 15 � LATIN SMALL LETTER A WITH RING ABOVE */ 61 NPC8, # 16 GREEK CAPITAL LETTER DELTA */ 62 95, # 17 _ LOW LINE */ 63 NPC8, # 18 GREEK CAPITAL LETTER PHI */ 64 NPC8, # 19 GREEK CAPITAL LETTER GAMMA */ 65 NPC8, # 20 GREEK CAPITAL LETTER LAMBDA */ 66 NPC8, # 21 GREEK CAPITAL LETTER OMEGA */ 67 NPC8, # 22 GREEK CAPITAL LETTER PI */ 68 NPC8, # 23 GREEK CAPITAL LETTER PSI */ 69 NPC8, # 24 GREEK CAPITAL LETTER SIGMA */ 70 NPC8, # 25 GREEK CAPITAL LETTER THETA */ 71 NPC8, # 26 GREEK CAPITAL LETTER XI */ 72 27, # 27 ESCAPE TO EXTENSION TABLE */ 73 198, # 28 � LATIN CAPITAL LETTER AE */ 74 230, # 29 � LATIN SMALL LETTER AE */ 75 223, # 30 � LATIN SMALL LETTER SHARP S (German) */ 76 201, # 31 � LATIN CAPITAL LETTER E WITH ACUTE */ 77 32, # 32 SPACE */ 78 33, # 33 ! EXCLAMATION MARK */ 79 34, # 34 " QUOTATION MARK */ 80 35, # 35 # NUMBER SIGN */ 81 164, # 36 � CURRENCY SIGN */ 82 37, # 37 % PERCENT SIGN */ 83 38, # 38 & AMPERSAND */ 84 39, # 39 ' APOSTROPHE */ 85 40, # 40 ( LEFT PARENTHESIS */ 86 41, # 41 ) RIGHT PARENTHESIS */ 87 42, # 42 * ASTERISK */ 88 43, # 43 + PLUS SIGN */ 89 44, # 44 , COMMA */ 90 45, # 45 - HYPHEN-MINUS */ 91 46, # 46 . FULL STOP */ 92 47, # 47 / SOLIDUS (SLASH) */ 93 48, # 48 0 DIGIT ZERO */ 94 49, # 49 1 DIGIT ONE */ 95 50, # 50 2 DIGIT TWO */ 96 51, # 51 3 DIGIT THREE */ 97 52, # 52 4 DIGIT FOUR */ 98 53, # 53 5 DIGIT FIVE */ 99 54, # 54 6 DIGIT SIX */ 100 55, # 55 7 DIGIT SEVEN */ 101 56, # 56 8 DIGIT EIGHT */ 102 57, # 57 9 DIGIT NINE */ 103 58, # 58 : COLON */ 104 59, # 59 ; SEMICOLON */ 105 60, # 60 < LESS-THAN SIGN */ 106 61, # 61 = EQUALS SIGN */ 107 62, # 62 > GREATER-THAN SIGN */ 108 63, # 63 ? QUESTION MARK */ 109 161, # 64 � INVERTED EXCLAMATION MARK */ 110 65, # 65 A LATIN CAPITAL LETTER A */ 111 66, # 66 B LATIN CAPITAL LETTER B */ 112 67, # 67 C LATIN CAPITAL LETTER C */ 113 68, # 68 D LATIN CAPITAL LETTER D */ 114 69, # 69 E LATIN CAPITAL LETTER E */ 115 70, # 70 F LATIN CAPITAL LETTER F */ 116 71, # 71 G LATIN CAPITAL LETTER G */ 117 72, # 72 H LATIN CAPITAL LETTER H */ 118 73, # 73 I LATIN CAPITAL LETTER I */ 119 74, # 74 J LATIN CAPITAL LETTER J */ 120 75, # 75 K LATIN CAPITAL LETTER K */ 121 76, # 76 L LATIN CAPITAL LETTER L */ 122 77, # 77 M LATIN CAPITAL LETTER M */ 123 78, # 78 N LATIN CAPITAL LETTER N */ 124 79, # 79 O LATIN CAPITAL LETTER O */ 125 80, # 80 P LATIN CAPITAL LETTER P */ 126 81, # 81 Q LATIN CAPITAL LETTER Q */ 127 82, # 82 R LATIN CAPITAL LETTER R */ 128 83, # 83 S LATIN CAPITAL LETTER S */ 129 84, # 84 T LATIN CAPITAL LETTER T */ 130 85, # 85 U LATIN CAPITAL LETTER U */ 131 86, # 86 V LATIN CAPITAL LETTER V */ 132 87, # 87 W LATIN CAPITAL LETTER W */ 133 88, # 88 X LATIN CAPITAL LETTER X */ 134 89, # 89 Y LATIN CAPITAL LETTER Y */ 135 90, # 90 Z LATIN CAPITAL LETTER Z */ 136 196, # 91 � LATIN CAPITAL LETTER A WITH DIAERESIS */ 137 214, # 92 � LATIN CAPITAL LETTER O WITH DIAERESIS */ 138 209, # 93 � LATIN CAPITAL LETTER N WITH TILDE */ 139 220, # 94 � LATIN CAPITAL LETTER U WITH DIAERESIS */ 140 167, # 95 � SECTION SIGN */ 141 191, # 96 � INVERTED QUESTION MARK */ 142 97, # 97 a LATIN SMALL LETTER A */ 143 98, # 98 b LATIN SMALL LETTER B */ 144 99, # 99 c LATIN SMALL LETTER C */ 145 100, # 100 d LATIN SMALL LETTER D */ 146 101, # 101 e LATIN SMALL LETTER E */ 147 102, # 102 f LATIN SMALL LETTER F */ 148 103, # 103 g LATIN SMALL LETTER G */ 149 104, # 104 h LATIN SMALL LETTER H */ 150 105, # 105 i LATIN SMALL LETTER I */ 151 106, # 106 j LATIN SMALL LETTER J */ 152 107, # 107 k LATIN SMALL LETTER K */ 153 108, # 108 l LATIN SMALL LETTER L */ 154 109, # 109 m LATIN SMALL LETTER M */ 155 110, # 110 n LATIN SMALL LETTER N */ 156 111, # 111 o LATIN SMALL LETTER O */ 157 112, # 112 p LATIN SMALL LETTER P */ 158 113, # 113 q LATIN SMALL LETTER Q */ 159 114, # 114 r LATIN SMALL LETTER R */ 160 115, # 115 s LATIN SMALL LETTER S */ 161 116, # 116 t LATIN SMALL LETTER T */ 162 117, # 117 u LATIN SMALL LETTER U */ 163 118, # 118 v LATIN SMALL LETTER V */ 164 119, # 119 w LATIN SMALL LETTER W */ 165 120, # 120 x LATIN SMALL LETTER X */ 166 121, # 121 y LATIN SMALL LETTER Y */ 167 122, # 122 z LATIN SMALL LETTER Z */ 168 228, # 123 � LATIN SMALL LETTER A WITH DIAERESIS */ 169 246, # 124 � LATIN SMALL LETTER O WITH DIAERESIS */ 170 241, # 125 � LATIN SMALL LETTER N WITH TILDE */ 171 252, # 126 � LATIN SMALL LETTER U WITH DIAERESIS */ 172 224, # 127 � LATIN SMALL LETTER A WITH GRAVE */ 173 174 # 12 27 10 FORM FEED 175 # 94 27 20 ^ CIRCUMFLEX ACCENT 176 # 123 27 40 { LEFT CURLY BRACKET 177 # 125 27 41 } RIGHT CURLY BRACKET 178 # 92 27 47 \ REVERSE SOLIDUS (BACKSLASH) 179 # 91 27 60 [ LEFT SQUARE BRACKET 180 # 126 27 61 ~ TILDE 181 # 93 27 62 ] RIGHT SQUARE BRACKET 182 # 124 27 64 | VERTICAL BAR */ 183); 184 185#my $gsm_charset = join '' => map chr => @GSM0338_TO_ISO8859; 186 187@Device::Gsm::Charset::ISO8859_TO_GSM0338 = ( 188 NPC7, # 0 null [NUL] */ 189 NPC7, # 1 start of heading [SOH] */ 190 NPC7, # 2 start of text [STX] */ 191 NPC7, # 3 end of text [ETX] */ 192 NPC7, # 4 end of transmission [EOT] */ 193 NPC7, # 5 enquiry [ENQ] */ 194 NPC7, # 6 acknowledge [ACK] */ 195 NPC7, # 7 bell [BEL] */ 196 NPC7, # 8 backspace [BS] */ 197 NPC7, # 9 horizontal tab [HT] */ 198 10, # 10 line feed [LF] */ 199 NPC7, # 11 vertical tab [VT] */ 200 10 + 256, # 12 form feed [FF] */ 201 13, # 13 carriage return [CR] */ 202 NPC7, # 14 shift out [SO] */ 203 NPC7, # 15 shift in [SI] */ 204 NPC7, # 16 data link escape [DLE] */ 205 NPC7, # 17 device control 1 [DC1] */ 206 NPC7, # 18 device control 2 [DC2] */ 207 NPC7, # 19 device control 3 [DC3] */ 208 NPC7, # 20 device control 4 [DC4] */ 209 NPC7, # 21 negative acknowledge [NAK] */ 210 NPC7, # 22 synchronous idle [SYN] */ 211 NPC7, # 23 end of trans. block [ETB] */ 212 NPC7, # 24 cancel [CAN] */ 213 NPC7, # 25 end of medium [EM] */ 214 NPC7, # 26 substitute [SUB] */ 215 NPC7, # 27 escape [ESC] */ 216 NPC7, # 28 file separator [FS] */ 217 NPC7, # 29 group separator [GS] */ 218 NPC7, # 30 record separator [RS] */ 219 NPC7, # 31 unit separator [US] */ 220 32, # 32 space */ 221 33, # 33 ! exclamation mark */ 222 34, # 34 " double quotation mark */ 223 35, # 35 # number sign */ 224 2, # 36 $ dollar sign */ 225 37, # 37 % percent sign */ 226 38, # 38 & ampersand */ 227 39, # 39 ' apostrophe */ 228 40, # 40 ( left parenthesis */ 229 41, # 41 ) right parenthesis */ 230 42, # 42 * asterisk */ 231 43, # 43 + plus sign */ 232 44, # 44 , comma */ 233 45, # 45 - hyphen */ 234 46, # 46 . period */ 235 47, # 47 / slash, */ 236 48, # 48 0 digit 0 */ 237 49, # 49 1 digit 1 */ 238 50, # 50 2 digit 2 */ 239 51, # 51 3 digit 3 */ 240 52, # 52 4 digit 4 */ 241 53, # 53 5 digit 5 */ 242 54, # 54 6 digit 6 */ 243 55, # 55 7 digit 7 */ 244 56, # 56 8 digit 8 */ 245 57, # 57 9 digit 9 */ 246 58, # 58 : colon */ 247 59, # 59 ; semicolon */ 248 60, # 60 < less-than sign */ 249 61, # 61 = equal sign */ 250 62, # 62 > greater-than sign */ 251 63, # 63 ? question mark */ 252 0, # 64 @ commercial at sign */ 253 65, # 65 A uppercase A */ 254 66, # 66 B uppercase B */ 255 67, # 67 C uppercase C */ 256 68, # 68 D uppercase D */ 257 69, # 69 E uppercase E */ 258 70, # 70 F uppercase F */ 259 71, # 71 G uppercase G */ 260 72, # 72 H uppercase H */ 261 73, # 73 I uppercase I */ 262 74, # 74 J uppercase J */ 263 75, # 75 K uppercase K */ 264 76, # 76 L uppercase L */ 265 77, # 77 M uppercase M */ 266 78, # 78 N uppercase N */ 267 79, # 79 O uppercase O */ 268 80, # 80 P uppercase P */ 269 81, # 81 Q uppercase Q */ 270 82, # 82 R uppercase R */ 271 83, # 83 S uppercase S */ 272 84, # 84 T uppercase T */ 273 85, # 85 U uppercase U */ 274 86, # 86 V uppercase V */ 275 87, # 87 W uppercase W */ 276 88, # 88 X uppercase X */ 277 89, # 89 Y uppercase Y */ 278 90, # 90 Z uppercase Z */ 279 60 + 256, # 91 [ left square bracket */ 280 47 + 256, # 92 \ backslash */ 281 62 + 256, # 93 ] right square bracket */ 282 20 + 256, # 94 ^ circumflex accent */ 283 17, # 95 _ underscore */ 284 -39, # 96 ` back apostrophe */ 285 97, # 97 a lowercase a */ 286 98, # 98 b lowercase b */ 287 99, # 99 c lowercase c */ 288 100, # 100 d lowercase d */ 289 101, # 101 e lowercase e */ 290 102, # 102 f lowercase f */ 291 103, # 103 g lowercase g */ 292 104, # 104 h lowercase h */ 293 105, # 105 i lowercase i */ 294 106, # 106 j lowercase j */ 295 107, # 107 k lowercase k */ 296 108, # 108 l lowercase l */ 297 109, # 109 m lowercase m */ 298 110, # 110 n lowercase n */ 299 111, # 111 o lowercase o */ 300 112, # 112 p lowercase p */ 301 113, # 113 q lowercase q */ 302 114, # 114 r lowercase r */ 303 115, # 115 s lowercase s */ 304 116, # 116 t lowercase t */ 305 117, # 117 u lowercase u */ 306 118, # 118 v lowercase v */ 307 119, # 119 w lowercase w */ 308 120, # 120 x lowercase x */ 309 121, # 121 y lowercase y */ 310 122, # 122 z lowercase z */ 311 40 + 256, # 123 { left brace */ 312 64 + 256, # 124 | vertical bar */ 313 41 + 256, # 125 } right brace */ 314 61 + 256, # 126 ~ tilde accent */ 315 NPC7, # 127 delete [DEL] */ 316 NPC7, # 128 */ 317 NPC7, # 129 */ 318 -39, # 130 low left rising single quote */ 319 -102, # 131 lowercase italic f */ 320 -34, # 132 low left rising double quote */ 321 NPC7, # 133 low horizontal ellipsis */ 322 NPC7, # 134 dagger mark */ 323 NPC7, # 135 double dagger mark */ 324 NPC7, # 136 letter modifying circumflex */ 325 NPC7, # 137 per thousand (mille) sign */ 326 -83, # 138 uppercase S caron or hacek */ 327 -39, # 139 left single angle quote mark */ 328 -214, # 140 uppercase OE ligature */ 329 NPC7, # 141 */ 330 NPC7, # 142 */ 331 NPC7, # 143 */ 332 NPC7, # 144 */ 333 -39, # 145 left single quotation mark */ 334 -39, # 146 right single quote mark */ 335 -34, # 147 left double quotation mark */ 336 -34, # 148 right double quote mark */ 337 -42, # 149 round filled bullet */ 338 -45, # 150 en dash */ 339 -45, # 151 em dash */ 340 -39, # 152 small spacing tilde accent */ 341 NPC7, # 153 trademark sign */ 342 -115, # 154 lowercase s caron or hacek */ 343 -39, # 155 right single angle quote mark */ 344 -111, # 156 lowercase oe ligature */ 345 NPC7, # 157 */ 346 NPC7, # 158 */ 347 -89, # 159 uppercase Y dieresis or umlaut */ 348 -32, # 160 � non-breaking space */ 349 64, # 161 � inverted exclamation mark */ 350 -99, # 162 � cent sign */ 351 1, # 163 � pound sterling sign */ 352 36, # 164 � general currency sign */ 353 3, # 165 � yen sign */ 354 -33, # 166 � broken vertical bar */ 355 95, # 167 � section sign */ 356 -34, # 168 � spacing dieresis or umlaut */ 357 NPC7, # 169 � copyright sign */ 358 NPC7, # 170 � feminine ordinal indicator */ 359 -60, # 171 � left (double) angle quote */ 360 NPC7, # 172 � logical not sign */ 361 -45, # 173 � soft hyphen */ 362 NPC7, # 174 � registered trademark sign */ 363 NPC7, # 175 � spacing macron (long) accent */ 364 NPC7, # 176 � degree sign */ 365 NPC7, # 177 � plus-or-minus sign */ 366 -50, # 178 � superscript 2 */ 367 -51, # 179 � superscript 3 */ 368 -39, # 180 � spacing acute accent */ 369 -117, # 181 � micro sign */ 370 NPC7, # 182 � paragraph sign, pilcrow sign */ 371 NPC7, # 183 � middle dot, centered dot */ 372 NPC7, # 184 � spacing cedilla */ 373 -49, # 185 � superscript 1 */ 374 NPC7, # 186 � masculine ordinal indicator */ 375 -62, # 187 � right (double) angle quote (guillemet) */ 376 NPC7, # 188 � fraction 1/4 */ 377 NPC7, # 189 � fraction 1/2 */ 378 NPC7, # 190 � fraction 3/4 */ 379 96, # 191 � inverted question mark */ 380 -65, # 192 � uppercase A grave */ 381 -65, # 193 � uppercase A acute */ 382 -65, # 194 � uppercase A circumflex */ 383 -65, # 195 � uppercase A tilde */ 384 91, # 196 � uppercase A dieresis or umlaut */ 385 14, # 197 � uppercase A ring */ 386 28, # 198 � uppercase AE ligature */ 387 9, # 199 � uppercase C cedilla */ 388 -31, # 200 � uppercase E grave */ 389 31, # 201 � uppercase E acute */ 390 -31, # 202 � uppercase E circumflex */ 391 -31, # 203 � uppercase E dieresis or umlaut */ 392 -73, # 204 � uppercase I grave */ 393 -73, # 205 � uppercase I acute */ 394 -73, # 206 � uppercase I circumflex */ 395 -73, # 207 � uppercase I dieresis or umlaut */ 396 -68, # 208 � uppercase ETH */ 397 93, # 209 � uppercase N tilde */ 398 -79, # 210 � uppercase O grave */ 399 -79, # 211 � uppercase O acute */ 400 -79, # 212 � uppercase O circumflex */ 401 -79, # 213 � uppercase O tilde */ 402 92, # 214 � uppercase O dieresis or umlaut */ 403 -42, # 215 � multiplication sign */ 404 11, # 216 � uppercase O slash */ 405 -85, # 217 � uppercase U grave */ 406 -85, # 218 � uppercase U acute */ 407 -85, # 219 � uppercase U circumflex */ 408 94, # 220 � uppercase U dieresis or umlaut */ 409 -89, # 221 � uppercase Y acute */ 410 NPC7, # 222 � uppercase THORN */ 411 30, # 223 � lowercase sharp s, sz ligature */ 412 127, # 224 � lowercase a grave */ 413 -97, # 225 � lowercase a acute */ 414 -97, # 226 � lowercase a circumflex */ 415 -97, # 227 � lowercase a tilde */ 416 123, # 228 � lowercase a dieresis or umlaut */ 417 15, # 229 � lowercase a ring */ 418 29, # 230 � lowercase ae ligature */ 419 -9, # 231 � lowercase c cedilla */ 420 4, # 232 � lowercase e grave */ 421 5, # 233 � lowercase e acute */ 422 -101, # 234 � lowercase e circumflex */ 423 -101, # 235 � lowercase e dieresis or umlaut */ 424 7, # 236 � lowercase i grave */ 425 -7, # 237 � lowercase i acute */ 426 -105, # 238 � lowercase i circumflex */ 427 -105, # 239 � lowercase i dieresis or umlaut */ 428 NPC7, # 240 � lowercase eth */ 429 125, # 241 � lowercase n tilde */ 430 8, # 242 � lowercase o grave */ 431 -111, # 243 � lowercase o acute */ 432 -111, # 244 � lowercase o circumflex */ 433 -111, # 245 � lowercase o tilde */ 434 124, # 246 � lowercase o dieresis or umlaut */ 435 -47, # 247 � division sign */ 436 12, # 248 � lowercase o slash */ 437 6, # 249 � lowercase u grave */ 438 -117, # 250 � lowercase u acute */ 439 -117, # 251 � lowercase u circumflex */ 440 126, # 252 � lowercase u dieresis or umlaut */ 441 -121, # 253 � lowercase y acute */ 442 NPC7, # 254 � lowercase thorn */ 443 -121 # 255 � lowercase y dieresis or umlaut */ 444); 445 446sub iso8859_to_gsm0338 { 447 my $ascii = shift; 448 return '' if !defined $ascii || $ascii eq ''; 449 450 my $gsm = ''; 451 my $n = 0; 452 for (; $n < length($ascii); $n++) { 453 my $ch_ascii = ord(substr($ascii, $n, 1)); 454 my $ch_gsm = $Device::Gsm::Charset::ISO8859_TO_GSM0338[$ch_ascii]; 455 456 # Is this a "replaced" char? 457 if ($ch_gsm <= 0xFF) { 458 $ch_gsm = abs($ch_gsm); 459 } 460 else { 461 462 # Prepend an escape char for extended char 463 $gsm .= chr(ESCAPE); 464 465 # Encode extended char 466 $ch_gsm -= 256; 467 } 468 469 #warn('char ['.$ch_ascii.'] => ['.$ch_gsm.']'); 470 $gsm .= chr($ch_gsm); 471 } 472 return $gsm; 473} 474 475sub gsm0338_to_iso8859 { 476 my $gsm = shift; 477 return '' if !defined $gsm || $gsm eq ''; 478 479 my $ascii = ''; 480 my $n = 0; 481 482 for (; $n < length($gsm); $n++) { 483 484 my $c = ord(substr($gsm, $n, 1)); 485 486 # Extended charset ? 487 if ($c == ESCAPE) { # "escape extended mode" 488 $n++; 489 $c = ord(substr($gsm, $n, 1)); 490 if ($c == 0x0A) { 491 $ascii .= chr(12); 492 } 493 elsif ($c == 0x14) { 494 $ascii .= '^'; 495 } 496 elsif ($c == 0x28) { 497 $ascii .= '{'; 498 } 499 elsif ($c == 0x29) { 500 $ascii .= '}'; 501 } 502 elsif ($c == 0x2F) { 503 $ascii .= '\\'; 504 } 505 elsif ($c == 0x3C) { 506 $ascii .= '['; 507 } 508 elsif ($c == 0x3D) { 509 $ascii .= '~'; 510 } 511 elsif ($c == 0x3E) { 512 $ascii .= ']'; 513 } 514 elsif ($c == 0x40) { 515 $ascii .= '|'; 516 } 517 elsif ($c == 0x65) { # 'e' 518 $ascii .= chr(164) 519 ; # iso_8859_15 EURO SIGN or iso_8859_1 CURRENCY_SIGN 520 } 521 else { 522 $ascii .= chr(NPC8); # Non printable 523 } 524 525 } 526 else { 527 528 # Standard GSM 3.38 encoding 529 $ascii .= chr($Device::Gsm::Charset::GSM0338_TO_ISO8859[$c]); 530 } 531 532 #warn('gsm char ['.$c.'] converted to ascii ['.ord(substr($ascii,-1)).']'); 533 } 534 535 return $ascii; 536} 537 538sub gsm0338_length { 539 my $ascii = shift; 540 my $gsm0338_length = 0; 541 my $n = 0; 542 for (; $n < length($ascii); $n++) { 543 my $ch_ascii = ord(substr($ascii, $n, 1)); 544 my $ch_gsm = $Device::Gsm::Charset::ISO8859_TO_GSM0338[$ch_ascii]; 545 546 # Is this a "replaced" char? 547 if ($ch_gsm <= 0xFF) { 548 $gsm0338_length++; 549 } 550 else { 551 $gsm0338_length += 2; 552 } 553 } 554 return $gsm0338_length; 555} 556 557sub gsm0338_split { 558 my $ascii = shift; 559 return '' if !defined $ascii || $ascii eq ''; 560 my @parts; 561 my $part; 562 my $chars_count = 0; 563 my $ascii_length = length($ascii); 564 while ($ascii_length) { 565 my $ch_ascii = substr($ascii, 0, 1); 566 my $ch_gsm 567 = $Device::Gsm::Charset::ISO8859_TO_GSM0338[ ord($ch_ascii) ]; 568 if ($chars_count < 153 and $ch_gsm <= 0xFF) { 569 $part .= $ch_ascii; 570 $chars_count++; 571 $ascii = substr($ascii, 1, $ascii_length--); 572 } 573 elsif ($chars_count < 152 and $ch_gsm > 0xFF) { 574 $part .= $ch_ascii; 575 $chars_count += 2; 576 $ascii = substr($ascii, 1, $ascii_length--); 577 } 578 else { 579 push(@parts, $part); 580 $part = ''; 581 $chars_count = 0; 582 } 583 } 584 push(@parts, $part); 585 return (@parts); 586} 5871; 588 589__END__ 590 591