reader_core.c.svn-base
上传用户:holyzs
上传日期:2022-06-29
资源大小:2335k
文件大小:11k
源码类别:

编辑器/阅读器

开发平台:

C/C++

  1. #include <reader_core.h>
  2. #include <reader_mmi.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. page_t reader_pages[MAX_PAGE];
  7. int reader_total_pages;
  8. static unsigned short reader_current_content[256*1024];
  9. static int reader_current_content_len;
  10. static int compact_layout;
  11. static int font_size;
  12. static int space_sizes[] = {8, 7};
  13. static int tab_sizes[] = {16, 14};
  14. static int font_sizes[] = {16, 14};
  15. static font_t *asc_fonts[] = {asc_font_16, asc_font_14};
  16. void draw_chr(screen_t s, int x, int y, unsigned short *matrix, int width, int fs, color_t color) {
  17.   int dy, dx;
  18.   unsigned short c;
  19.   for (dy = 0; dy < fs; dy++) {
  20.     c = matrix[dy];
  21.     for (dx = 0; dx < width; dx++) {
  22.       if (c & (1 << dx)) {
  23.         reader_setpixel(s, x + dx, y + dy, color);
  24.       }
  25.     }
  26.   }
  27. }
  28. //binary search wide char c in unicode table tab
  29. //if found c in tab return the index of c
  30. //else return -1
  31. static int binary_search(unsigned short c, unsigned short *tab, int n) {
  32.   int low = 0;
  33.   int high = n - 1;
  34.   int mid;
  35.   while (low <= high) {
  36.     mid = (low + high) / 2;
  37.     if (c < tab[mid]) {
  38.       high = mid - 1;
  39.     } else if (c > tab[mid]) {
  40.       low = mid + 1;
  41.     } else {
  42.       return mid;
  43.     }
  44.   }
  45.   return -1;
  46. }
  47. int get_chr_width(unsigned short c, int fs) {
  48.   int b = ((fs == DEFAULT_FONT_SIZE) ? 0 : 1);
  49.   if (c <= 0xff) { //ascii, variable width
  50.     switch (c) {
  51.     case 0x20:
  52.       return space_sizes[b];
  53.     case 0x09:
  54.       return tab_sizes[b];
  55.     case 0x0a: //ignore 'n'
  56.     case 0x0d: //ignore 'r'
  57.       return 0;
  58.     default:
  59.       return asc_fonts[b][c].width;
  60.     }
  61.   }
  62.   return font_sizes[b];
  63. }
  64. int reader_textout_ex(screen_t s, int x, int y, unsigned short *str, int n, int fs, color_t color, unsigned int flag) {
  65.   unsigned short c;
  66.   int index, width;
  67.   int cnt = 0;
  68.   int b = ((fs == DEFAULT_FONT_SIZE) ? 0 : 1);
  69.   font_t *asc_font = asc_fonts[b];
  70. #ifdef WIN32
  71.   unsigned short buf[1024];
  72.   assert(n >= 0 && n < 1024);
  73.   memcpy(buf, str, 2*n);
  74.   buf[n] = 0;
  75.   READER_TRACEW((L"%sn",buf));
  76. #endif
  77.   //skip unicode flag
  78.   if (*str == 0xfeff) {
  79.     str ++;
  80.     n --;
  81.   }
  82.   if (n == 0) {
  83.     return 0;
  84.   }
  85.   if (flag & TEXT_OUT_ALIGN_RIGHT) {
  86.     width = 0;
  87.     cnt = 0;
  88.     while (((c = str[cnt]) != 0) && (cnt < n)) {
  89.       width += get_chr_width(c, fs);
  90.       cnt ++;
  91.     }
  92.     x -= width;
  93.   }
  94.   cnt = 0;
  95.   while (((c = *str) != 0) && (cnt < n)) {
  96.     width = get_chr_width(c, fs);
  97.     if (width > 0) {
  98.       if (c <= 0xff && ! isspace(c)) { //ascii, variable width
  99.         draw_chr(s, x, y, asc_font[c].matrix, width, fs, color);
  100.       } else { //gb2312, fixed-width
  101.         index = binary_search(c, uni_table, FONT_TOTAL);
  102.         if (index >= 0) {
  103.           if (fs == DEFAULT_FONT_SIZE) {
  104.             draw_chr(s, x, y, chn_font_matrix_16[index], width, fs, color);
  105.           } else {
  106.             draw_chr(s, x, y, chn_font_matrix_14[index], width, fs, color);
  107.           }          
  108.         }
  109.         //we just leave it blank for unknown chars now, maybe we can draw a question mark or square instead...
  110.       }
  111.       x += width;
  112.     }
  113.     str ++;
  114.     cnt ++;
  115.   }
  116.   return cnt;
  117. }
  118. enum {
  119.   WHOLE_SPACE = 0x3000, /*全角空格*/
  120.   WHOLE_PERIOD = 0x3002, /*。*/
  121.   WHOLE_QUESTION = 0xff1f, /*?*/
  122.   WHOLE_EXCALMATORY = 0xff01, /*!*/
  123.   WHOLE_REVERSE_QUOTATION = 0x201d, /*”*/
  124.   WHOLE_COLON = 0xff1a /*:*/
  125. };
  126. #define reader_isspace(c) ((c) == ' ' || (c) == 'r' || (c) == 'n' || (c) == 't' || (c) == WHOLE_SPACE)
  127. #define reader_isletter(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
  128. #define reader_ismark(c) ((c) == ',' || (c) == '.' || (c) == '!' || (c) == '?' || (c) == '"' || (c) == ':' || (c) == ';' || (c) == ''')
  129. #define reader_is_sentence_end(c) ((c) == 'n' || (c) == WHOLE_PERIOD || (c) == WHOLE_QUESTION || (c) == WHOLE_EXCALMATORY || (c) == WHOLE_REVERSE_QUOTATION || (c) == WHOLE_COLON || (c) == '.' || (c) == '!' || (c) == '?' || (c) == '"')
  130. int reader_last_page_lines;
  131. int reader_last_line_chars;
  132. int reader_format_pages(unsigned short *content, int n) {
  133.   int np = 0, nl = 1;
  134.   int i;
  135.   unsigned short c, lookahead, lookbehind;
  136.   int width;
  137.   int last_space = -1; //for word indicator in English layout
  138.   int need_nl = 0, skip = 0;
  139.   int fs = reader_get_font_size();
  140.   int max_line = reader_get_max_line(fs);
  141.   int x_start = reader_get_start_x(fs);
  142.   int x_off = x_start;
  143.   if (n == 0) {
  144.     return np + 1;
  145.   }
  146.   reader_pages[0].page_offset = 0;
  147.   reader_pages[0].line_offest[0] = 0;
  148.   for (i = 0; i < n; i++) {
  149.     c = content[i];
  150.     width = get_chr_width(c, font_size);
  151.     if (c == ' ') {
  152.       last_space = i;
  153.     } else if (c > 0x7f) {
  154.       //not keep a whole word when processing non-English
  155.       last_space = -1;
  156.     }
  157.     if (c == 'n') { //switch to next line
  158.       if (i < n - 1) {
  159.         //new line when 
  160.         //1. not compact layout
  161.         //or 2. multiple new lines
  162.         //or 3. a space followed
  163.         //or 4. a end mark of a sentence preceded
  164.         if ((! compact_layout)
  165.           || ((i > 0) && ((lookbehind = content[i - 1]) != 0) && reader_is_sentence_end(lookbehind))
  166.           || (((lookahead = content[i + 1]) != 0) && reader_isspace(lookahead))) {
  167.           READER_TRACE(("n---p%d l%d %d, switch at enter.---n", np, nl, i));
  168.           x_off = x_start;
  169.           need_nl = 1;
  170.           skip = 1;  //skip 'n'
  171.           i ++;
  172.         }
  173.       }
  174.     } else {
  175.       x_off += width;
  176.       READER_TRACE(("%c off=%dn", c, x_off));
  177.       
  178.       if (x_off > READER_SCREEN_WIDTH) { //switch to next line
  179.         need_nl = 1;
  180.         if (last_space < 0) { //no space encountered
  181.           READER_TRACE(("n---p%d l%d %d(%c), switch at offset %d.---n", np, nl, i, content[i], x_off));
  182.           x_off = width + x_start; //put the overbound char to next line
  183.         } else {
  184.           if (reader_isletter(c) || reader_ismark(c)) { //do not split the word or word and the following mark
  185.             x_off = x_start;
  186.             i = last_space;
  187.             skip = 1; //skip space
  188.             i ++;
  189.           } else {
  190.             x_off = width + x_start; //put the overbound char to next line
  191.           }
  192.         }
  193.       }
  194.     }
  195.     if (need_nl) {
  196.       need_nl = 0;
  197.       last_space = -1;
  198.       if (nl == max_line) { //switch to next page
  199.         if (np == MAX_PAGE - 1) {
  200.           reader_last_page_lines = nl;
  201.           reader_last_line_chars = i - (reader_pages[np].page_offset + reader_pages[np].line_offest[nl - 1]);
  202.           return np + 1;
  203.         }
  204.         np ++;
  205.         reader_pages[np].page_offset = i;
  206.         reader_pages[np].line_offest[0] = 0;
  207.         nl = 1;
  208.       } else {
  209.         reader_pages[np].line_offest[nl ++] = i - reader_pages[np].page_offset; //skip 'n'
  210.       }
  211.       if (skip) { //already skipped, 
  212.         skip = 0;
  213.         i --;
  214.       }
  215.     }
  216.   }
  217.   reader_last_page_lines = nl;
  218.   reader_last_line_chars = i - (reader_pages[np].page_offset + reader_pages[np].line_offest[nl - 1]);
  219.   READER_TRACE(("last lines=%d last chars=%dn", reader_last_page_lines, reader_last_line_chars));
  220.   return np + 1;
  221. }
  222. int reader_init(unsigned short *dirname, unsigned short *filename) {
  223.   int pg;
  224.   int n, sz;
  225.   fsal_file_handle_t fd;
  226.   reader_individual_saver_t saver;
  227.   int ret;
  228.   if (dirname != NULL) {
  229.     if ((ret = reader_file_set_dir(dirname)) != 0) {
  230.       return ret;
  231.     }
  232.   }
  233.   if (filename != NULL) {
  234.     reader_set_current_file(filename);
  235.     if ((ret = reader_file_set_cursor_by_name(filename)) < 0) {
  236.       return ERR_SET_CURSOR_BY_NAME;
  237.     }
  238.   } else {
  239.     filename = reader_get_current_file();
  240.   }
  241.   //construct a sliding window for file content
  242. #if TRACE_FILENAME
  243.   {
  244.   FILE *dbgfd;
  245.   dbgfd = fopen("initname", "wb");
  246.   fwrite(filename, 2, reader_wcslen(filename), dbgfd);
  247.   fclose(dbgfd);
  248.   }
  249. #endif
  250.   fd = fsal_open(filename, "rb");
  251.   if (fd == 0) {
  252.     return ERR_OPEN_FILE;
  253.   }
  254.   n = fsal_read(&saver, sizeof(saver), 1, fd);
  255.   if ((n != 1) || (strcmp(saver.magic, "DRB") != 0)) {
  256.     return ERR_FILE_FORMAT;
  257.   }
  258.   sz = sizeof(reader_current_content)/sizeof(unsigned short);
  259.   reader_current_content_len = fsal_read(reader_current_content, sizeof(unsigned short), sz, fd);
  260.   fsal_close(fd);
  261.   reader_set_layout(saver.file_saver.parts.layout, 0);
  262.   //format when all options are set
  263.   reader_total_pages = reader_format_pages(reader_current_content, reader_current_content_len);
  264.   READER_TRACEM(("reader_total_pages=%dn", reader_total_pages));
  265.   pg = saver.file_saver.parts.page_number;
  266.   if (pg > 0 && pg < reader_total_pages - 1) {
  267.     //restore the last time position
  268.     //if come to the last page, read from the beginning
  269.     reader_set_current_page(pg);
  270.   } else {
  271.     //read from the beginning
  272.     reader_set_current_page(0);
  273.   }
  274.   return 0;
  275. }
  276. void reader_init_content(unsigned short *text, int size) {
  277.   reader_set_layout(0, 0);
  278.   reader_total_pages = reader_format_pages(text, size);
  279.   reader_set_current_page(0);
  280. }
  281. int reader_get_layout(void) {
  282.   return compact_layout;
  283. }
  284. static int locate_page(unsigned int offset, int n) {
  285.   int i;
  286.   for (i = 0; i < n - 2; i += 2) {
  287.     if (offset >= reader_pages[i].page_offset && offset < reader_pages[i + 2].page_offset) {
  288.       return i;
  289.     }
  290.   }
  291.   return i;
  292. }
  293. static void reformat_text(void) {
  294.   unsigned int pg_off;
  295.   pg_off = reader_pages[reader_get_current_page()].page_offset;
  296.   reader_total_pages = reader_format_pages(reader_current_content, reader_current_content_len);
  297.   reader_set_current_page(locate_page(pg_off, reader_total_pages));
  298. }
  299. void reader_set_layout(int compact, int reformat) {
  300.   int ns = (compact != 0);
  301.   if (ns != compact_layout) {
  302.     compact_layout = ns;
  303.     if (reformat) {
  304.       reformat_text();
  305.     }
  306.   }
  307. }
  308. int reader_get_font_size(void) {
  309.   return font_size;
  310. }
  311. void reader_set_font_size(int fs, int reformat) {
  312.   //adjust unsaved font size value
  313.   if (fs != DEFAULT_FONT_SIZE &&  fs != 14) {
  314.     fs = DEFAULT_FONT_SIZE;
  315.   }
  316.   if (fs != font_size) {
  317.     font_size = fs;
  318.     if (reformat) {
  319.       reformat_text();
  320.     }
  321.   }
  322. }
  323. int reader_switch_font_size(void) {
  324.   int new_size;
  325.   if (font_size == DEFAULT_FONT_SIZE) {
  326.     new_size = 14;
  327.   } else {
  328.     new_size = DEFAULT_FONT_SIZE;
  329.   }
  330.   //invoked by user, must reformat text
  331.   reader_set_font_size(new_size, 1);
  332.   return new_size;
  333. }
  334. int reader_get_max_line(int fs) {
  335.   switch (fs) {
  336.   case DEFAULT_FONT_SIZE:
  337.     return 13;
  338.   case 14:
  339.     return MAX_LINE; //smallest font uses MAX_LINE
  340.   default:
  341.     assert(0);
  342.   }
  343.   //never reach here
  344.   return -1;
  345. }
  346. unsigned short *reader_get_current_content(int *size) {
  347.   if (size) {
  348.     *size = reader_current_content_len;
  349.   }
  350.   return reader_current_content;
  351. }