00001
00002
00003
00004 #include <cstdlib>
00005 #include <stdio.h>
00006
00007 #include "mythlogging.h"
00008 #include "cc708reader.h"
00009 #include "cc708decoder.h"
00010
00011 #define LOC QString("CC708: ")
00012
00013 #define DEBUG_CAPTIONS 0
00014 #define DEBUG_CC_SERVICE 0
00015 #define DEBUG_CC_SERVICE_2 0
00016 #define DEBUG_CC_RAWPACKET 0
00017 #define DEBUG_CC_VALIDPACKET 0
00018 #define DEBUG_CC_SERVICE_BLOCK 0
00019
00020 typedef enum
00021 {
00022 NTSC_CC_f1 = 0,
00023 NTSC_CC_f2 = 1,
00024 DTVCC_PACKET_DATA = 2,
00025 DTVCC_PACKET_START = 3,
00026 } kCCTypes;
00027
00028 const char* cc_types[4] =
00029 {
00030 "NTSC line 21 field 1 closed captions"
00031 "NTSC line 21 field 2 closed captions"
00032 "DTVCC Channel Packet Data"
00033 "DTVCC Channel Packet Start"
00034 };
00035
00036 static void parse_cc_packet(CC708Reader *cb_cbs, CaptionPacket *pkt,
00037 time_t last_seen[64]);
00038
00039 void CC708Decoder::decode_cc_data(uint cc_type, uint data1, uint data2)
00040 {
00041 if (DTVCC_PACKET_START == cc_type)
00042 {
00043 #if 0
00044 LOG(VB_VBI, LOG_DEBUG, LOC + QString("CC ST data(0x%1 0x%2)")
00045 .arg(data1,0,16).arg(data2,0,16));
00046 #endif
00047
00048 if (partialPacket.size && reader)
00049 parse_cc_packet(reader, &partialPacket, last_seen);
00050
00051 partialPacket.data[0] = data1;
00052 partialPacket.data[1] = data2;
00053 partialPacket.size = 2;
00054 }
00055 else if (DTVCC_PACKET_DATA == cc_type)
00056 {
00057 #if 0
00058 LOG(VB_VBI, LOG_DEBUG, LOC + QString("CC Ex data(0x%1 0x%2)")
00059 .arg(data1,0,16).arg(data2,0,16));
00060 #endif
00061
00062 partialPacket.data[partialPacket.size + 0] = data1;
00063 partialPacket.data[partialPacket.size + 1] = data2;
00064 partialPacket.size += 2;
00065 }
00066 }
00067
00068 void CC708Decoder::decode_cc_null(void)
00069 {
00070 if (partialPacket.size && reader)
00071 parse_cc_packet(reader, &partialPacket, last_seen);
00072 partialPacket.size = 0;
00073 }
00074
00075 void CC708Decoder::services(uint seconds, bool seen[64]) const
00076 {
00077 time_t now = time(NULL);
00078 time_t then = now - seconds;
00079
00080 seen[0] = false;
00081 for (uint i = 1; i < 64; i++)
00082 seen[i] = (last_seen[i] >= then);
00083 }
00084
00085 typedef enum
00086 {
00087 NUL = 0x00,
00088 ETX = 0x03,
00089 BS = 0x08,
00090 FF = 0x0C,
00091 CR = 0x0D,
00092 HCR = 0x0E,
00093 EXT1 = 0x10,
00094 P16 = 0x18,
00095 } C0;
00096
00097 typedef enum
00098 {
00099 CW0=0x80, CW1, CW2, CW3, CW4, CW5, CW6, CW7,
00100 CLW, DSW, HDW, TGW, DLW, DLY, DLC, RST,
00101 SPA=0x90, SPC, SPL, SWA=0x97,
00102 DF0, DF1, DF2, DF3, DF4, DF5, DF6, DF7,
00103 } C1;
00104
00105 extern ushort CCtableG0[0x60];
00106 extern ushort CCtableG1[0x60];
00107 extern ushort CCtableG2[0x60];
00108 extern ushort CCtableG3[0x60];
00109
00110 static void append_character(CC708Reader *cc, uint service_num, short ch);
00111 static void parse_cc_service_stream(CC708Reader *cc, uint service_num);
00112 static int handle_cc_c0_ext1_p16(CC708Reader *cc, uint service_num, int i);
00113 static int handle_cc_c1(CC708Reader *cc, uint service_num, int i);
00114 static int handle_cc_c2(CC708Reader *cc, uint service_num, int i);
00115 static int handle_cc_c3(CC708Reader *cc, uint service_num, int i);
00116
00117 #define SEND_STR \
00118 do { \
00119 if (cc->temp_str_size[service_num]) \
00120 { \
00121 cc->TextWrite(service_num, \
00122 cc->temp_str[service_num], \
00123 cc->temp_str_size[service_num]); \
00124 cc->temp_str_size[service_num] = 0; \
00125 } \
00126 } while (0)
00127
00128 static void parse_cc_service_stream(CC708Reader* cc, uint service_num)
00129 {
00130 const int blk_size = cc->buf_size[service_num];
00131 int blk_start = 0, dlc_loc = 0, rst_loc = 0, i = 0;
00132
00133
00134 for (i = 0; i < blk_size; i++)
00135 {
00136 switch (cc->buf[service_num][i]) {
00137
00138
00139 case CLW:
00140 case DLW:
00141 case DSW:
00142 case HDW:
00143 case TGW:
00144 case DLY:
00145 i += 1;
00146 break;
00147 case SPA:
00148 case SPL:
00149 i += 2;
00150 break;
00151 case SPC:
00152 i += 3;
00153 break;
00154 case SWA:
00155 i += 4;
00156 break;
00157 case DF0:
00158 case DF1:
00159 case DF2:
00160 case DF3:
00161 case DF4:
00162 case DF5:
00163 case DF6:
00164 case DF7:
00165 i += 6;
00166 break;
00167
00168 case RST:
00169 rst_loc = dlc_loc = i;
00170 break;
00171 case DLC:
00172 dlc_loc = i;
00173 break;
00174 }
00175 }
00176
00177
00178 if (rst_loc)
00179 {
00180 cc->Reset(service_num);
00181 cc->delayed[service_num] = 0;
00182 blk_start = rst_loc + 1;
00183 }
00184
00185
00186 if (dlc_loc && cc->delayed[service_num])
00187 {
00188 cc->DelayCancel(service_num);
00189 cc->delayed[service_num] = 0;
00190 }
00191
00192
00193 if (cc->delayed[service_num] && blk_size >= 126)
00194 {
00195 cc->DelayCancel(service_num);
00196 cc->delayed[service_num] = 0;
00197 dlc_loc = blk_size - 1;
00198 }
00199
00200 #if 0
00201 LOG(VB_VBI, LOG_ERR,
00202 QString("cc_ss delayed(%1) blk_start(%2) blk_size(%3)")
00203 .arg(cc->delayed) .arg(blk_start) .arg(blk_size));
00204 #endif
00205
00206 for (i = (cc->delayed[service_num]) ? blk_size : blk_start;
00207 i < blk_size; )
00208 {
00209 const int old_i = i;
00210 const int code = cc->buf[service_num][i];
00211 if (0x0 == code)
00212 {
00213 i++;
00214 }
00215 else if (code <= 0x1f)
00216 {
00217
00218 i = handle_cc_c0_ext1_p16(cc, service_num, i);
00219 }
00220 else if (code <= 0x7f)
00221 {
00222
00223 short character = CCtableG0[code-0x20];
00224 append_character(cc, service_num, character);
00225 i++;
00226 SEND_STR;
00227 }
00228 else if (code <= 0x9f)
00229 {
00230
00231 i = handle_cc_c1(cc, service_num, i);
00232 }
00233 else if (code <= 0xff)
00234 {
00235
00236 short character = CCtableG1[code-0xA0];
00237 append_character(cc, service_num, character);
00238 i++;
00239 }
00240
00241 #if DEBUG_CC_SERVICE
00242 LOG(VB_VBI, LOG_DEBUG, QString("i %1, blk_size %2").arg(i)
00243 .arg(blk_size));
00244 #endif
00245
00246
00247 if (old_i == i)
00248 {
00249 #if DEBUG_CC_SERVICE
00250 LOG(VB_VBI, LOG_DEBUG, QString("old_i == i == %1").arg(i));
00251 QString msg;
00252 for (int j = 0; j < blk_size; j++)
00253 msg += QString("0x%1 ").arg(cc->buf[service_num][j], 0, 16);
00254 LOG(VB_VBI, LOG_DEBUG, msg);
00255 #endif
00256 if (blk_size - i > 10)
00257 {
00258 LOG(VB_VBI, LOG_INFO, "eia-708 decoding error...");
00259 cc->Reset(service_num);
00260 cc->delayed[service_num] = 0;
00261 i = cc->buf_size[service_num];
00262 }
00263
00264 break;
00265 }
00266 else if (cc->delayed[service_num] && dlc_loc < i)
00267 {
00268
00269 break;
00270 }
00271 else if (cc->delayed[service_num])
00272 {
00273
00274 cc->DelayCancel(service_num);
00275 cc->delayed[service_num] = 0;
00276 }
00277 }
00278
00279
00280 if ((blk_size - i) > 0)
00281 {
00282 memmove(cc->buf[service_num], cc->buf[service_num] + i,
00283 blk_size - i);
00284 cc->buf_size[service_num] -= i;
00285 }
00286 else
00287 {
00288 if (0 != (blk_size - i))
00289 {
00290 LOG(VB_VBI, LOG_ERR, QString("buffer error i(%1) buf_size(%2)")
00291 .arg(i).arg(blk_size));
00292 QString msg;
00293 for (i=0; i < blk_size; i++)
00294 msg += QString("0x%1 ").arg(cc->buf[service_num][i], 0, 16);
00295 LOG(VB_VBI, LOG_ERR, msg);
00296 }
00297 cc->buf_size[service_num] = 0;
00298 }
00299 }
00300
00301 static int handle_cc_c0_ext1_p16(CC708Reader* cc, uint service_num, int i)
00302 {
00303
00304 const int code = cc->buf[service_num][i];
00305 if (code<=0xf)
00306 {
00307
00308 if (ETX==code)
00309 SEND_STR;
00310 else if (BS==code)
00311 append_character(cc, service_num, 0x08);
00312 else if (FF==code)
00313 append_character(cc, service_num, 0x0c);
00314 else if (CR==code)
00315 append_character(cc, service_num, 0x0d);
00316 else if (HCR==code)
00317 append_character(cc, service_num, 0x0d);
00318 i++;
00319 }
00320 else if (code<=0x17)
00321 {
00322
00323 const int blk_size = cc->buf_size[service_num];
00324 if (EXT1==code && ((i+1)<blk_size))
00325 {
00326 const int code2 = cc->buf[service_num][i+1];
00327 if (code2<=0x1f)
00328 {
00329
00330 i = handle_cc_c2(cc, service_num, i+1);
00331 }
00332 else if (code2<=0x7f)
00333 {
00334
00335 append_character(cc, service_num, CCtableG2[code2-0x20]);
00336 i+=2;
00337 }
00338 else if (code2<=0x9f)
00339 {
00340
00341 i = handle_cc_c3(cc, service_num, i);
00342 }
00343 else if (code2<=0xff)
00344 {
00345
00346 append_character(cc, service_num, CCtableG3[code2-0xA0]);
00347 i+=2;
00348 }
00349 }
00350 else if ((i+1)<blk_size)
00351 i+=2;
00352 }
00353 else if (code<=0x1f)
00354 {
00355
00356 const int blk_size = cc->buf_size[service_num];
00357 if (P16==code && ((i+2)<blk_size))
00358 {
00359
00360 }
00361 if ((i+2)<blk_size)
00362 i+=3;
00363 }
00364 return i;
00365 }
00366
00367 static int handle_cc_c1(CC708Reader* cc, uint service_num, int i)
00368 {
00369 const int blk_size = cc->buf_size[service_num];
00370 const int code = cc->buf[service_num][i];
00371
00372 const unsigned char* blk_buf = cc->buf[service_num];
00373 if (code<=CW7)
00374 {
00375 SEND_STR;
00376 cc->SetCurrentWindow(service_num, code-0x80);
00377 i+=1;
00378 }
00379 else if (DLC == cc->buf[service_num][i])
00380 {
00381
00382
00383
00384
00385 i+=1;
00386 }
00387 else if (code>=CLW && code<=DLY && ((i+1)<blk_size))
00388 {
00389 int param1 = blk_buf[i+1];
00390 SEND_STR;
00391 if (CLW==code)
00392 cc->ClearWindows(service_num, param1);
00393 else if (DSW==code)
00394 cc->DisplayWindows(service_num, param1);
00395 else if (HDW==code)
00396 cc->HideWindows(service_num, param1);
00397 else if (TGW==code)
00398 cc->ToggleWindows(service_num, param1);
00399 else if (DLW==code)
00400 cc->DeleteWindows(service_num, param1);
00401 else if (DLY==code)
00402 {
00403 cc->Delay(service_num, param1);
00404 cc->delayed[service_num] = 1;
00405 }
00406 i+=2;
00407 }
00408 else if (SPA==code && ((i+2)<blk_size))
00409 {
00410 int pen_size = (blk_buf[i+1] ) & 0x3;
00411 int offset = (blk_buf[i+1]>>2) & 0x3;
00412 int text_tag = (blk_buf[i+1]>>4) & 0xf;
00413 int font_tag = (blk_buf[i+2] ) & 0x7;
00414 int edge_type = (blk_buf[i+2]>>3) & 0x7;
00415 int underline = (blk_buf[i+2]>>6) & 0x1;
00416 int italic = (blk_buf[i+2]>>7) & 0x1;
00417 SEND_STR;
00418 cc->SetPenAttributes(service_num, pen_size, offset, text_tag,
00419 font_tag, edge_type, underline, italic);
00420 i+=3;
00421 }
00422 else if (SPC==code && ((i+3)<blk_size))
00423 {
00424 int fg_color = (blk_buf[i+1] ) & 0x3f;
00425 int fg_opacity = (blk_buf[i+1]>>6) & 0x03;
00426 int bg_color = (blk_buf[i+2] ) & 0x3f;
00427 int bg_opacity = (blk_buf[i+2]>>6) & 0x03;
00428 int edge_color = (blk_buf[i+3]>>6) & 0x3f;
00429 SEND_STR;
00430 cc->SetPenColor(service_num, fg_color, fg_opacity,
00431 bg_color, bg_opacity, edge_color);
00432 i+=4;
00433 }
00434 else if (SPL==code && ((i+2)<blk_size))
00435 {
00436 int row = blk_buf[i+1] & 0x0f;
00437 int col = blk_buf[i+2] & 0x3f;
00438 SEND_STR;
00439 cc->SetPenLocation(service_num, row, col);
00440 i+=3;
00441 }
00442 else if (SWA==code && ((i+4)<blk_size))
00443 {
00444 int fill_color = (blk_buf[i+1] ) & 0x3f;
00445 int fill_opacity = (blk_buf[i+1]>>6) & 0x03;
00446 int border_color = (blk_buf[i+2] ) & 0x3f;
00447 int border_type01 = (blk_buf[i+2]>>6) & 0x03;
00448 int justify = (blk_buf[i+3] ) & 0x03;
00449 int scroll_dir = (blk_buf[i+3]>>2) & 0x03;
00450 int print_dir = (blk_buf[i+3]>>4) & 0x03;
00451 int word_wrap = (blk_buf[i+3]>>6) & 0x01;
00452 int border_type = (blk_buf[i+3]>>5) | border_type01;
00453 int display_eff = (blk_buf[i+4] ) & 0x03;
00454 int effect_dir = (blk_buf[i+4]>>2) & 0x03;
00455 int effect_speed = (blk_buf[i+4]>>4) & 0x0f;
00456 SEND_STR;
00457 cc->SetWindowAttributes(
00458 service_num, fill_color, fill_opacity, border_color, border_type,
00459 scroll_dir, print_dir, effect_dir,
00460 display_eff, effect_speed, justify, word_wrap);
00461 i+=5;
00462 }
00463 else if ((code>=DF0) && (code<=DF7) && ((i+6)<blk_size))
00464 {
00465
00466 int priority = ( blk_buf[i+1] ) & 0x7;
00467 int col_lock = (blk_buf[i+1]>>3) & 0x1;
00468 int row_lock = (blk_buf[i+1]>>4) & 0x1;
00469 int visible = (blk_buf[i+1]>>5) & 0x1;
00470
00471 int anchor_vertical = blk_buf[i+2] & 0x7f;
00472 int relative_pos = (blk_buf[i+2]>>7);
00473
00474 int anchor_horizontal = blk_buf[i+3];
00475
00476 int row_count = blk_buf[i+4] & 0xf;
00477 int anchor_point = blk_buf[i+4]>>4;
00478
00479 int col_count = blk_buf[i+5] & 0x3f;
00480
00481 int pen_style = blk_buf[i+6] & 0x7;
00482 int win_style = (blk_buf[i+6]>>3) & 0x7;
00483 SEND_STR;
00484 cc->DefineWindow(service_num, code-0x98, priority, visible,
00485 anchor_point, relative_pos,
00486 anchor_vertical, anchor_horizontal,
00487 row_count, col_count, row_lock, col_lock,
00488 pen_style, win_style);
00489 i+=7;
00490 }
00491 #if DEBUG_CC_SERVICE
00492 else
00493 {
00494 LOG(VB_VBI, LOG_ERR, QString("handle_cc_c1: (NOT HANDLED) "
00495 "code(0x%1) i(%2) blk_size(%3)").arg(code, 2, 16, '0')
00496 .arg(i).arg(blk_size));
00497 }
00498 #endif
00499
00500 return i;
00501 }
00502
00503 static int handle_cc_c2(CC708Reader* cc, uint service_num, int i)
00504 {
00505 const int blk_size = cc->buf_size[service_num];
00506 const int code = cc->buf[service_num][i+1];
00507
00508 if ((code<=0x7) && ((i+1)<blk_size)){
00509 i+=2;
00510 SEND_STR;
00511 }
00512 else if ((code<=0xf) && ((i+2)<blk_size))
00513 {
00514 i+=3;
00515 SEND_STR;
00516 }
00517 else if ((code<=0x17) && ((i+3)<blk_size))
00518 {
00519 i+=4;
00520 SEND_STR;
00521 }
00522 else if ((code<=0x1f) && ((i+4)<blk_size))
00523 {
00524 i+=5;
00525 SEND_STR;
00526 }
00527 return i;
00528 }
00529
00530 static int handle_cc_c3(CC708Reader* cc, uint service_num, int i)
00531 {
00532 const unsigned char* blk_buf = cc->buf[service_num];
00533 const int blk_size = cc->buf_size[service_num];
00534 const int code = cc->buf[service_num][i+1];
00535
00536 if ((code<=0x87) && ((i+5)<blk_size))
00537 {
00538 i+=6;
00539 SEND_STR;
00540 }
00541 else if ((code<=0x8f) && ((i+6)<blk_size))
00542 {
00543 i+=7;
00544 SEND_STR;
00545 }
00546 else if ((i+2)<blk_size)
00547 {
00548 int length = blk_buf[i+2]&0x3f;
00549 if ((i+length)<blk_size)
00550 {
00551 i+=1+length;
00552 SEND_STR;
00553 }
00554 }
00555 return i;
00556 }
00557
00558 static void rightsize_buf(CC708Reader* cc, uint service_num, uint block_size)
00559 {
00560 uint min_new_size = block_size + cc->buf_size[service_num];
00561 if (min_new_size >= cc->buf_alloc[service_num])
00562 {
00563 uint new_alloc = cc->buf_alloc[service_num];
00564 for (uint i = 0; (i < 32) && (new_alloc <= min_new_size); i++)
00565 new_alloc *= 2;
00566
00567 cc->buf[service_num] =
00568 (unsigned char*) realloc(cc->buf[service_num], new_alloc);
00569 cc->buf_alloc[service_num] = (cc->buf[service_num]) ? new_alloc : 0;
00570
00571 #if DEBUG_CC_SERVICE_2
00572 LOG(VB_VBI, LOG_DEBUG, QString("rightsize_buf: srv %1 to %1 bytes")
00573 .arg(service_num) .arg(cc->buf_alloc[service_num]));
00574 #endif
00575 }
00576 if (min_new_size >= cc->buf_alloc[service_num])
00577 LOG(VB_VBI, LOG_ERR,
00578 QString("buffer resize error: min_new_size=%1, buf_alloc[%2]=%3")
00579 .arg(min_new_size)
00580 .arg(service_num)
00581 .arg(cc->buf_alloc[service_num]));
00582 }
00583
00584 static void append_cc(CC708Reader* cc, uint service_num,
00585 const unsigned char* blk_buf, int block_size)
00586 {
00587 rightsize_buf(cc, service_num, block_size);
00588
00589 memcpy(cc->buf[service_num] + cc->buf_size[service_num],
00590 blk_buf, block_size);
00591
00592 cc->buf_size[service_num] += block_size;
00593 #if DEBUG_CC_SERVICE_2
00594 {
00595 uint i;
00596 QString msg("append_cc: ");
00597 for (i = 0; i < cc->buf_size[service_num]; i++)
00598 msg += QString("0x%1").arg(cc->buf[service_num][i], 0, 16);
00599 LOG(VB_VBI, LOG_DEBUG, msg);
00600 }
00601 #endif
00602 parse_cc_service_stream(cc, service_num);
00603 }
00604
00605 static void parse_cc_packet(CC708Reader* cb_cbs, CaptionPacket* pkt,
00606 time_t last_seen[64])
00607 {
00608 const unsigned char* pkt_buf = pkt->data;
00609 const int pkt_size = pkt->size;
00610 int off = 1;
00611 int service_number = 0;
00612 int block_data_offset = 0;
00613 int len = ((((int)pkt_buf[0]) & 0x3f)<<1) - 1;
00614 int seq_num = (((int)pkt_buf[0])>>6)&0x3;
00615
00616 if (len < 0)
00617 return;
00618
00619 #if DEBUG_CC_RAWPACKET
00620 if (1)
00621 #elif DEBUG_CAPTIONS
00622 if (len > pkt_size)
00623 #else
00624 if (0)
00625 #endif
00626 {
00627 int j;
00628 int srv = (pkt_buf[off]>>5) & 0x7;
00629 QString msg = QString("CC708 len %1 srv0 %2 seq %3 ").arg(len, 2)
00630 .arg(srv) .arg(seq_num);
00631 for (j = 0; j < pkt_size; j++)
00632 msg += QString("0x%1").arg(pkt_buf[j], 0, 16);
00633 LOG(VB_VBI, LOG_DEBUG, msg);
00634 }
00635
00636 if (pkt_size >= 127)
00637 LOG(VB_VBI, LOG_ERR,
00638 QString("Unexpected pkt_size=%1").arg(pkt_size));
00639
00640 while (off < pkt_size && pkt_buf[off])
00641 {
00642 int block_size = pkt_buf[off] & 0x1f;
00643 service_number = (pkt_buf[off]>>5) & 0x7;
00644 block_data_offset = (0x7==service_number && block_size!=0) ?
00645 off+2 : off+1;
00646 #if DEBUG_CC_SERVICE_BLOCK
00647 LOG(VB_VBI, LOG_DEBUG,
00648 QString("service_block size(%1) num(%2) off(%3)")
00649 .arg(block_size) .arg(service_number) .arg(block_data_offset));
00650 #endif
00651 if (off+2 == block_data_offset)
00652 {
00653 int extended_service_number = pkt_buf[off+2] & 0x3f;
00654 #if DEBUG_CC_SERVICE_BLOCK
00655 LOG(VB_VBI, LOG_DEBUG, QString("ext_svc_num(%1)")
00656 .arg(extended_service_number));
00657 #endif
00658 service_number = extended_service_number;
00659 }
00660 if (service_number)
00661 {
00662 #if DEBUG_CC_SERVICE
00663 int i;
00664 if (!(2==block_size &&
00665 0==pkt_buf[block_data_offset] &&
00666 0==pkt_buf[block_data_offset+1]))
00667 {
00668 QString msg = QString("service %1: ").arg(service_number);
00669 for (i=0; i<block_size; i++)
00670 msg += QString("0x%1 ")
00671 .arg(pkt_buf[block_data_offset+i], 0, 16);
00672 LOG(VB_VBI, LOG_DEBUG, msg);
00673 }
00674 #endif
00675 append_cc(cb_cbs, service_number,
00676 &pkt_buf[block_data_offset], block_size);
00677
00678 last_seen[service_number] = time(NULL);
00679 }
00680 off+=block_size+1;
00681 }
00682 if (off<pkt_size)
00683 {
00684 if (pkt_buf[off] != 0)
00685 LOG(VB_VBI, LOG_ERR,
00686 QString("CEA-708 packet error: pkt_size=%1, pkt_buf[%2]=%3")
00687 .arg(pkt_size).arg(off).arg(pkt_buf[off]));
00688 }
00689 }
00690
00691 static void append_character(CC708Reader *cc, uint service_num, short ch)
00692 {
00693 if (cc->temp_str_size[service_num]+2 > cc->temp_str_alloc[service_num])
00694 {
00695 int new_alloc = (cc->temp_str_alloc[service_num]) ?
00696 cc->temp_str_alloc[service_num] * 2 : 64;
00697
00698 cc->temp_str[service_num] = (short*)
00699 realloc(cc->temp_str[service_num], new_alloc * sizeof(short));
00700
00701 cc->temp_str_alloc[service_num] = new_alloc;
00702 }
00703
00704 if (cc->temp_str[service_num])
00705 {
00706 int i = cc->temp_str_size[service_num];
00707 cc->temp_str[service_num][i] = ch;
00708 cc->temp_str_size[service_num]++;
00709 }
00710 else
00711 {
00712 cc->temp_str_size[service_num] = 0;
00713 cc->temp_str_alloc[service_num]=0;
00714 }
00715 }
00716
00717 ushort CCtableG0[0x60] =
00718 {
00719
00720
00721 ' ', '!','\"', '#', '$', '%', '&', '\'',
00722 '(', ')', '*', '+', ',', '-', '.', '/',
00723 '0', '1', '2', '3', '4', '5', '6', '7',
00724 '8', '9', ':', ';', '<', '=', '>', '?',
00725
00726 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
00727 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
00728 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
00729 'X', 'Y', 'Z', '[', '\\',']', '^', '_',
00730
00731 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
00732 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
00733 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
00734 'x', 'y', 'z', '{', '|', '}', '~', 0x266a,
00735 };
00736
00737 ushort CCtableG1[0x60] =
00738 {
00739
00740
00741
00742
00743 0xA0,
00744 (uchar)'¡', (uchar)'¢', (uchar)'£',
00745 (uchar)'¤', (uchar)'¥', (uchar)'¦', (uchar)'§',
00746 (uchar)'¨', (uchar)'©', (uchar)'ª', (uchar)'«',
00747 (uchar)'¬', (uchar)'', (uchar)'®', (uchar)'¯',
00748 (uchar)'°', (uchar)'±', (uchar)'²', (uchar)'³',
00749 (uchar)'´', (uchar)'µ', (uchar)'¶', (uchar)'·',
00750 (uchar)'¸', (uchar)'¹', (uchar)'º', (uchar)'»',
00751 (uchar)'¼', (uchar)'½', (uchar)'¾', (uchar)'¿',
00752
00753 (uchar)'À', (uchar)'Á', (uchar)'Â', (uchar)'Ã',
00754 (uchar)'Ä', (uchar)'Å', (uchar)'Æ', (uchar)'Ç',
00755 (uchar)'È', (uchar)'É', (uchar)'Ê', (uchar)'Ë',
00756 (uchar)'Ì', (uchar)'Í', (uchar)'Î', (uchar)'Ï',
00757 (uchar)'Ð', (uchar)'Ñ', (uchar)'Ò', (uchar)'Ó',
00758 (uchar)'Ô', (uchar)'Õ', (uchar)'Ö', (uchar)'×',
00759 (uchar)'Ø', (uchar)'Ù', (uchar)'Ú', (uchar)'Û',
00760 (uchar)'Ü', (uchar)'Ý', (uchar)'Þ', (uchar)'ß',
00761
00762 (uchar)'à', (uchar)'á', (uchar)'â', (uchar)'ã',
00763 (uchar)'ä', (uchar)'å', (uchar)'æ', (uchar)'ç',
00764 (uchar)'è', (uchar)'é', (uchar)'ê', (uchar)'ë',
00765 (uchar)'ì', (uchar)'í', (uchar)'î', (uchar)'ï',
00766 (uchar)'ð', (uchar)'ñ', (uchar)'ò', (uchar)'ó',
00767 (uchar)'ô', (uchar)'õ', (uchar)'ö', (uchar)'÷',
00768 (uchar)'ø', (uchar)'ù', (uchar)'ú', (uchar)'û',
00769 (uchar)'ü', (uchar)'ý', (uchar)'þ', (uchar)'ÿ',
00770 };
00771
00772 ushort CCtableG2[0x60] =
00773 {
00774 ' ',
00775 0xA0,
00776 0, 0,
00777 0, 0x2026,
00778 0, 0,
00779 0, 0,
00780 0x160,
00781 0x152, 0,
00782 0, 0,
00783 0x2588, 0x2018,
00784 0x2019, 0x201c,
00785 0x201d, 0xB7,
00786 0, 0,
00787 0, 0x2122,
00788 0x161,
00789 0x153, 0x2120,
00790 0, 0x178,
00791
00792
00793
00794
00795
00796 0, 0, 0, 0,
00797 0, 0, 0, 0,
00798 0, 0, 0, 0,
00799 0, 0, 0, 0,
00800
00801 0, 0, 0, 0,
00802 0, 0, 0, 0,
00803 0, 0, 0, 0,
00804 0, 0, 0, 0,
00805
00806 0, 0, 0, 0,
00807 0, 0, 0, 0,
00808 0, 0, 0, 0,
00809 0, 0, 0, 0,
00810
00811 0, 0,
00812 0, 0,
00813 0, 0,
00814 0x215b, 0x215c,
00815 0x215d, 0x215e,
00816 0x2502, 0x2510,
00817 0x2514, 0x2500,
00818 0x2518, 0x250c,
00819 };
00820
00821 ushort CCtableG3[0x60] =
00822 {
00823
00824 '#',
00825 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00826 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00827
00828 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00829 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00830
00831 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00833 };