1 //
2 // C++ Implementation: jinke/lbook V3 viewer plugin
3 //
4 // Description:
5 //
6 //
7 // Author: Vadim Lopatin <vadim.lopatin@coolreader.org>, (C) 2008
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 
13 // support DBUS interface signals
14 #ifndef ENABLE_DBUS_VIEWER_EVENTS
15 #define ENABLE_DBUS_VIEWER_EVENTS 0
16 #endif
17 
18 // flash leds while long operation
19 #ifndef LEDTHREAD
20 #define LEDTHREAD 0
21 #endif
22 
23 // uncomment following line to allow running executables named .exe.txt
24 #define ALLOW_RUN_EXE 1
25 // uncomment to use separate .ini files for different formats
26 #define SEPARATE_INI_FILES 1
27 
28 #include <unistd.h>
29 #include <sys/wait.h>
30 #include "cr3jinke.h"
31 #include <crengine.h>
32 #include <crgui.h>
33 
34 #if ENABLE_DBUS_VIEWER_EVENTS==1
35 #define DBUS_API_SUBJECT_TO_CHANGE
36 #include <dbus/dbus.h>
37 #endif
38 
39 #include <microwin/nano-X.h>
40 #include <microwin/nxcolors.h>
41 #include "cr3main.h"
42 #include "mainwnd.h"
43 
44 #include <pthread.h>
45 #include <fcntl.h>
46 #include <sys/ioctl.h>
47 #include <unistd.h>
48 #include <semaphore.h>
49 
50 //#include <math.h>
51 
52 #define min(a,b) ((a)<(b)?(a):(b))
53 #define max(a,b) ((a)>(b)?(a):(b))
54 
55 
56 
57 static bool firstDocUpdate = true;
58 
59 
60 status_info_t lastState = {0,0,0};
61 
62 static char last_bookmark[2048]= {0};
63 static int last_bookmark_page = 0;
64 
65 //static bool shuttingDown = false;
66 
67 #define USE_JINKE_USER_DATA 0
68 #define USE_OWN_BATTERY_TEST 0
69 
70 static int batteryState = -1;
71 
checkPowerState()72 int checkPowerState()
73 {
74     FILE * fp = fopen("/tmp/batteryinfo", "rb");
75     char buf[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
76     int batteryvalue=0;
77     if (fp) {
78         fread(buf, 1, 20, fp);
79         batteryvalue=atoi(buf);
80         CRLog::trace("/tmp/batteryinfo = %d", batteryvalue);
81         if (batteryvalue>4 || batteryvalue<0)
82             batteryvalue=4;//6
83         batteryvalue = batteryvalue * 100 / 4;
84         batteryState = batteryvalue;
85         fclose(fp);
86     } else {
87 #if USE_OWN_BATTERY_TEST==1
88         FILE * f = fopen( "/dev/misc/s3c2410_batt", "rb" );
89         if ( !f ) {
90 #endif
91             batteryState = 100;
92             CRLog::debug("cannot read battery state");
93 #if USE_OWN_BATTERY_TEST==1
94         } else {
95             int ch = fgetc( f );
96             fclose(f);
97             if ( ch == ' ' )
98                 batteryState = -1;
99             else if ( ch>=0 && ch <= 16 )
100                 batteryState = ch * 100 / 16;
101             else
102                 batteryState = 100;
103         }
104 #endif
105     }
106     return batteryState;
107 }
108 
109 #include <cri18n.h>
110 
111 #define VIEWER_WINDOW_X         0
112 #define VIEWER_WINDOW_Y         0
113 #define VIEWER_WINDOW_WIDTH    600
114 #define VIEWER_WINDOW_HEIGHT   800
115 
116 #ifndef USE_OLD_NANOX
117 
118 #define COLOR_LEVEL     4 //
119 #define BMPBUFGRAYLEVEL 2 //
120 #define BMP_PANEL_NUBS   (1<<COLOR_LEVEL)//
121 
122 const  unsigned long  panel256[]={
123 0X00000000,0X00010101,0X00020202,0X00030303,0X00040404,0X00050505,0X00060606,0X00070707,
124 0X00080808,0X00090909,0X000a0a0a,0X000b0b0b,0X000c0c0c,0X000d0d0d,0X000e0e0e,0X000f0f0f,
125 0X00101010,0X00111111,0X00121212,0X00131313,0X00141414,0X00151515,0X00161616,0X00171717,
126 0X00181818,0X00191919,0X001a1a1a,0X001b1b1b,0X001c1c1c,0X001d1d1d,0X001e1e1e,0X001f1f1f,
127 0X00202020,0X00212121,0X00222222,0X00232323,0X00242424,0X00252525,0X00262626,0X00272727,
128 0X00282828,0X00292929,0X002a2a2a,0X002b2b2b,0X002c2c2c,0X002d2d2d,0X002e2e2e,0X002f2f2f,
129 0X00303030,0X00313131,0X00323232,0X00333333,0X00343434,0X00353535,0X00363636,0X00373737,
130 0X00383838,0X00393939,0X003a3a3a,0X003b3b3b,0X003c3c3c,0X003d3d3d,0X003e3e3e,0X003f3f3f,
131 0X00404040,0X00414141,0X00424242,0X00434343,0X00444444,0X00454545,0X00464646,0X00474747,
132 0X00484848,0X00494949,0X004a4a4a,0X004b4b4b,0X004c4c4c,0X004d4d4d,0X004e4e4e,0X004f4f4f,
133 0X00505050,0X00515151,0X00525252,0X00535353,0X00545454,0X00555555,0X00565656,0X00575757,
134 0X00585858,0X00595959,0X005a5a5a,0X005b5b5b,0X005c5c5c,0X005d5d5d,0X005e5e5e,0X005f5f5f,
135 0X00606060,0X00616161,0X00626262,0X00636363,0X00646464,0X00656565,0X00666666,0X00676767,
136 0X00686868,0X00696969,0X006a6a6a,0X006b6b6b,0X006c6c6c,0X006d6d6d,0X006e6e6e,0X006f6f6f,
137 0X00707070,0X00717171,0X00727272,0X00737373,0X00747474,0X00757575,0X00767676,0X00777777,
138 0X00787878,0X00797979,0X007a7a7a,0X007b7b7b,0X007c7c7c,0X007d7d7d,0X007e7e7e,0X007f7f7f,
139 0X00808080,0X00818181,0X00828282,0X00838383,0X00848484,0X00858585,0X00868686,0X00878787,
140 0X00888888,0X00898989,0X008a8a8a,0X008b8b8b,0X008c8c8c,0X008d8d8d,0X008e8e8e,0X008f8f8f,
141 0X00909090,0X00919191,0X00929292,0X00939393,0X00949494,0X00959595,0X00969696,0X00979797,
142 0X00989898,0X00999999,0X009a9a9a,0X009b9b9b,0X009c9c9c,0X009d9d9d,0X009e9e9e,0X009f9f9f,
143 0X00a0a0a0,0X00a1a1a1,0X00a2a2a2,0X00a3a3a3,0X00a4a4a4,0X00a5a5a5,0X00a6a6a6,0X00a7a7a7,
144 0X00a8a8a8,0X00a9a9a9,0X00aaaaaa,0X00ababab,0X00acacac,0X00adadad,0X00aeaeae,0X00afafaf,
145 0X00b0b0b0,0X00b1b1b1,0X00b2b2b2,0X00b3b3b3,0X00b4b4b4,0X00b5b5b5,0X00b6b6b6,0X00b7b7b7,
146 0X00b8b8b8,0X00b9b9b9,0X00bababa,0X00bbbbbb,0X00bcbcbc,0X00bdbdbd,0X00bebebe,0X00bfbfbf,
147 0X00c0c0c0,0X00c1c1c1,0X00c2c2c2,0X00c3c3c3,0X00c4c4c4,0X00c5c5c5,0X00c6c6c6,0X00c7c7c7,
148 0X00c8c8c8,0X00c9c9c9,0X00cacaca,0X00cbcbcb,0X00cccccc,0X00cdcdcd,0X00cecece,0X00cfcfcf,
149 0X00d0d0d0,0X00d1d1d1,0X00d2d2d2,0X00d3d3d3,0X00d4d4d4,0X00d5d5d5,0X00d6d6d6,0X00d7d7d7,
150 0X00d8d8d8,0X00d9d9d9,0X00dadada,0X00dbdbdb,0X00dcdcdc,0X00dddddd,0X00dedede,0X00dfdfdf,
151 0X00e0e0e0,0X00e1e1e1,0X00e2e2e2,0X00e3e3e3,0X00e4e4e4,0X00e5e5e5,0X00e6e6e6,0X00e7e7e7,
152 0X00e8e8e8,0X00e9e9e9,0X00eaeaea,0X00ebebeb,0X00ececec,0X00ededed,0X00eeeeee,0X00efefef,
153 0X00f0f0f0,0X00f1f1f1,0X00f2f2f2,0X00f3f3f3,0X00f4f4f4,0X00f5f5f5,0X00f6f6f6,0X00f7f7f7,
154 0X00f8f8f8,0X00f9f9f9,0X00fafafa,0X00fbfbfb,0X00fcfcfc,0X00fdfdfd,0X00fefefe,0X00ffffff,
155 };
156 const unsigned long panel16[256]={
157 0x00000000,0x00505050,0x00808080,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
158 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
159 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
160 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
161 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
162 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
163 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
164 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
165 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
166 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
167 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
168 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
169 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
170 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
171 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
172 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
173 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
174 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
175 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
176 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
177 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
178 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
179 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
180 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
181 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
182 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
183 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
184 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
185 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
186 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
187 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
188 0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,
189 };
190 
191 
192 typedef struct
193 {
194     unsigned short int  bfType;
195     unsigned long bfSize;
196     unsigned short int  bfReserved1;
197     unsigned short int  bfReserved2;
198     unsigned long bfOffBits;
199 }BITMAPFILEHEADER;
200 #define BITMAPFILEHEADER_SIZE 14
201 
202 typedef struct
203 {
204     unsigned long biSize;
205     long biWidth;
206     long biHeight;
207     unsigned short int biPlanes;
208     unsigned short int biBitCount;
209     unsigned long biCompression;
210     unsigned long biSizeImage;
211     long biXPelsPerMeter;
212     long biYPelsPerMeter;
213     unsigned long biClrUsed;
214     unsigned long biClrImportant;
215 }BITMAPINFOHEADER;
216 #define BITMAPINFOHEADER_SIZE sizeof(BITMAPINFOHEADER)
217 
218 typedef struct
219 {
220     BITMAPFILEHEADER FileHeader;
221     BITMAPINFOHEADER BmpInfo;
222     MWPALENTRY   BmpPanel[BMP_PANEL_NUBS];
223 }BMPHEADER_16;
224 
225 typedef struct
226 {
227     BITMAPFILEHEADER FileHeader;
228     BITMAPINFOHEADER BmpInfo;
229     MWPALENTRY   BmpPanel[256];
230 }BMPHEADER_256;
231 
GrBitmapEx_Apollo_FOUR(GR_WINDOW_ID id,GR_GC_ID gc,int x,int y,int width,int height,int src_x,int src_y,int src_width,int src_height,GR_CHAR * imagebits)232 int GrBitmapEx_Apollo_FOUR(GR_WINDOW_ID id,GR_GC_ID gc,int x,int y,int width,int height,int src_x,int src_y, int src_width,int src_height, GR_CHAR *imagebits)
233 
234 {
235     // TODO: Add extra validation here
236     //4 bit 16 level degree color
237 
238 
239     BMPHEADER_256 lpHeader;
240     GR_IMAGE_ID ImageId;
241     int HeaderLen;
242     int i;
243     int Lines;
244     int BmpBufBytsPerLine=0,BytesPerLine=0;
245 
246     unsigned char char1,char2,char3,char4,BmpChar1;
247     unsigned char *Screen_Buf=NULL,*BmpFileBuf=NULL,*BufPtr=NULL,*HeaderBuf=NULL;
248     int GrayLevel=8;//256 gray level
249     int BmpWidth=0,BmpHeight=0,PixesPerByte=0,BmpPanelNumbers=0,Bmpheadersize=0;
250 
251     BmpWidth=min(width,src_width);
252     BmpHeight=min(height,src_height);
253 
254     PixesPerByte=8/GrayLevel;
255     BmpPanelNumbers=1<<GrayLevel;
256     BytesPerLine=(BmpWidth*GrayLevel+31)/32*4;
257     BmpBufBytsPerLine=(src_width*2+7)/8;
258 
259 
260     i=sizeof(BMPHEADER_256);
261     HeaderLen=BITMAPFILEHEADER_SIZE+sizeof(BITMAPINFOHEADER)+sizeof(MWPALENTRY)*BmpPanelNumbers;
262     memcpy((unsigned char *)&lpHeader.FileHeader.bfType,"BM",2);
263     lpHeader.FileHeader.bfSize=(BmpHeight*BytesPerLine)/PixesPerByte+HeaderLen;
264     lpHeader.FileHeader.bfReserved1=0;
265     lpHeader.FileHeader.bfReserved2=0;
266     lpHeader.FileHeader.bfOffBits=HeaderLen;
267     lpHeader.BmpInfo.biSize=sizeof(BITMAPINFOHEADER);
268     lpHeader.BmpInfo.biWidth=BmpWidth;
269     lpHeader.BmpInfo.biHeight=BmpHeight;
270     lpHeader.BmpInfo.biPlanes=1;
271     lpHeader.BmpInfo.biBitCount=GrayLevel;
272     lpHeader.BmpInfo.biCompression=0;
273     lpHeader.BmpInfo.biSizeImage=lpHeader.FileHeader.bfSize-HeaderLen;
274     lpHeader.BmpInfo.biXPelsPerMeter=0x257E;
275     lpHeader.BmpInfo.biYPelsPerMeter=0x257E;
276     lpHeader.BmpInfo.biClrUsed=0;
277     lpHeader.BmpInfo.biClrImportant=0;
278 
279     Bmpheadersize=HeaderLen;
280     BmpFileBuf=new unsigned char[BmpHeight*BytesPerLine+Bmpheadersize];
281 
282     if(!BmpFileBuf)
283     {
284         return 1;
285     }
286     memset(BmpFileBuf,0x0,BmpHeight*BytesPerLine+Bmpheadersize);
287     HeaderBuf=BmpFileBuf;
288     Screen_Buf=BmpFileBuf+Bmpheadersize;
289     BufPtr=Screen_Buf;
290 
291     memcpy(HeaderBuf,(char *)&lpHeader.FileHeader.bfType,2);
292     memcpy(&HeaderBuf[2],(char *)&lpHeader.FileHeader.bfSize,4);
293     memcpy(&HeaderBuf[6],(char *)&lpHeader.FileHeader.bfReserved1,2);
294     memcpy(&HeaderBuf[8],(char *)&lpHeader.FileHeader.bfReserved2,2);
295     memcpy(&HeaderBuf[10],(char *)&lpHeader.FileHeader.bfOffBits,4);
296     HeaderBuf+=BITMAPFILEHEADER_SIZE;
297     memcpy(HeaderBuf,(unsigned char *)&lpHeader.BmpInfo,BITMAPINFOHEADER_SIZE);
298     HeaderBuf+=BITMAPINFOHEADER_SIZE;
299     memcpy(HeaderBuf,(unsigned char *)&panel16,sizeof(MWPALENTRY)*BmpPanelNumbers);
300     HeaderBuf=BmpFileBuf;
301 
302     Lines=0;
303     //4 color degress change to 16 color degress,mainframe_img_bits is 4 color degress
304     for(Lines=0;Lines<BmpHeight;Lines++)
305     {
306 
307         char1=0;
308         char2=0;
309         char3=0;
310         char4=0;
311         //
312         BufPtr=(unsigned char *)&Screen_Buf[(BmpHeight-1-Lines)*BytesPerLine];
313         for(i=0;i<(BmpWidth*2+7)/8;i++)
314         {
315             BmpChar1=imagebits[i+(Lines+src_y)*BmpBufBytsPerLine+src_x/4];
316             //
317             char1=BmpChar1&0xc0;
318             char1>>=6;
319             *BufPtr=char1;
320             BufPtr++;
321             char2=BmpChar1&0x30;
322             char2>>=4;
323             *BufPtr=char2;
324             BufPtr++;
325             char3=BmpChar1&0x0c;
326             char3>>=2;
327             *BufPtr=char3;
328             BufPtr++;
329             char4=BmpChar1&0x03;
330             *BufPtr=char4;
331             BufPtr++;
332         }
333     }
334     ImageId=GrLoadImageFromBuffer(BmpFileBuf,lpHeader.FileHeader.bfSize,GR_BACKGROUND_TOPLEFT);
335     GrDrawImageToFit(id,gc,x,y,BmpWidth,BmpHeight,ImageId);
336     GrFreeImage(ImageId);
337     delete[] BmpFileBuf;
338     return 0;
339 }
340 
GrBitmapEx_Apollo_NEW(GR_WINDOW_ID id,GR_GC_ID gc,int x,int y,int width,int height,int src_x,int src_y,int src_width,int src_height,GR_CHAR * imagebits)341 int GrBitmapEx_Apollo_NEW(GR_WINDOW_ID id,GR_GC_ID gc,int x,int y,int width,int height,int src_x,int src_y, int src_width,int src_height, GR_CHAR *imagebits)
342 {
343 
344     BMPHEADER_256 lpHeader;
345     GR_IMAGE_ID ImageId;
346     int HeaderLen;
347     int i;
348     int Lines;
349     int BmpBufBytsPerLine=0,BytesPerLine=0;
350 
351 
352     unsigned char char1,char2,char3,char4,BmpChar1;
353     unsigned char *Screen_Buf=NULL,*BmpFileBuf=NULL,*BufPtr=NULL,*HeaderBuf=NULL,*pimg = NULL;
354     int GrayLevel=8;//256 gray level
355     int BmpWidth=0,BmpHeight=0,PixesPerByte=0,BmpPanelNumbers=0,Bmpheadersize=0;
356     BmpWidth=min(width,src_width);
357     BmpHeight=min(height,src_height-src_y);
358 //  BmpHeight=min(height,src_height);
359     if(BmpHeight<=0)
360         BmpHeight=1;
361 
362     PixesPerByte=8/GrayLevel;
363     BmpPanelNumbers=1<<GrayLevel;
364     BytesPerLine=(BmpWidth*GrayLevel+31)/32*4;//
365     BmpBufBytsPerLine=(((src_width*GrayLevel+7)/8+3)/4)*4;
366 
367 
368     i=sizeof(BMPHEADER_256);
369     HeaderLen=BITMAPFILEHEADER_SIZE+sizeof(BITMAPINFOHEADER)+sizeof(MWPALENTRY)*BmpPanelNumbers;
370     memcpy((unsigned char *)&lpHeader.FileHeader.bfType,"BM",2);//
371     lpHeader.FileHeader.bfSize=(BmpHeight*BytesPerLine)/PixesPerByte+HeaderLen; //
372     lpHeader.FileHeader.bfReserved1=0;//
373     lpHeader.FileHeader.bfReserved2=0;//
374     lpHeader.FileHeader.bfOffBits=HeaderLen;//
375     lpHeader.BmpInfo.biSize=sizeof(BITMAPINFOHEADER);//BMP
376     lpHeader.BmpInfo.biWidth=BmpWidth;//
377     lpHeader.BmpInfo.biHeight=BmpHeight;//
378     lpHeader.BmpInfo.biPlanes=1;//
379     lpHeader.BmpInfo.biBitCount=GrayLevel;//
380     lpHeader.BmpInfo.biCompression=0;
381     lpHeader.BmpInfo.biSizeImage=lpHeader.FileHeader.bfSize-HeaderLen;
382     lpHeader.BmpInfo.biXPelsPerMeter=0x257E;
383     lpHeader.BmpInfo.biYPelsPerMeter=0x257E;
384     lpHeader.BmpInfo.biClrUsed=0;
385     lpHeader.BmpInfo.biClrImportant=0;
386 
387     Bmpheadersize=HeaderLen;
388     BmpFileBuf=new unsigned char[BmpHeight*BytesPerLine+Bmpheadersize];
389 
390     if(!BmpFileBuf)
391     {
392         return 1;
393     }
394     memset(BmpFileBuf,0xFF,BmpHeight*BytesPerLine+Bmpheadersize);
395     HeaderBuf=BmpFileBuf;
396     Screen_Buf=BmpFileBuf+Bmpheadersize;
397     BufPtr=Screen_Buf;
398 
399     memcpy(HeaderBuf,(char *)&lpHeader.FileHeader.bfType,2);
400     memcpy(&HeaderBuf[2],(char *)&lpHeader.FileHeader.bfSize,4);
401     memcpy(&HeaderBuf[6],(char *)&lpHeader.FileHeader.bfReserved1,2);
402     memcpy(&HeaderBuf[8],(char *)&lpHeader.FileHeader.bfReserved2,2);
403     memcpy(&HeaderBuf[10],(char *)&lpHeader.FileHeader.bfOffBits,4);
404     HeaderBuf+=BITMAPFILEHEADER_SIZE;
405     memcpy(HeaderBuf,(unsigned char *)&lpHeader.BmpInfo,BITMAPINFOHEADER_SIZE);
406     HeaderBuf+=BITMAPINFOHEADER_SIZE;
407     memcpy(HeaderBuf,(unsigned char *)&panel256,sizeof(MWPALENTRY)*BmpPanelNumbers);
408     HeaderBuf=BmpFileBuf;
409 
410     Lines=0;
411     BufPtr = (unsigned char *)(Screen_Buf+(BmpHeight-1)*BytesPerLine);
412     pimg = (unsigned char *)(imagebits + src_y*BmpBufBytsPerLine +src_x);
413     for(Lines=0;Lines<BmpHeight;Lines++)
414     {
415 //printf("%s line = %d,height =%d,byte = %d,buf =%d\n",__FUNCTION__,Lines,BmpHeight,BytesPerLine,BufPtr);
416 //      BufPtr=(unsigned char *)&Screen_Buf[(BmpHeight-1-Lines)*BytesPerLine];
417 //      memcpy(BufPtr,(unsigned char *)&imagebits[(Lines+src_y)*BmpBufBytsPerLine+src_x],BytesPerLine);
418         memcpy(BufPtr,pimg,BytesPerLine);
419         BufPtr -= BytesPerLine;
420         pimg += BmpBufBytsPerLine;
421     }
422 
423 
424 
425 
426     ImageId=GrLoadImageFromBuffer(BmpFileBuf,lpHeader.FileHeader.bfSize,GR_BACKGROUND_TOPLEFT);
427 
428     GrDrawImageToFit(id,gc,x,y,BmpWidth,BmpHeight,ImageId);
429     printf("x=%d,y=%d,BmpWidth=%d,BmpHeight=%d\n",x,y,BmpWidth,BmpHeight);
430     GrFreeImage(ImageId);
431 
432     delete[] BmpFileBuf;
433     return 0;
434 }
435 
436 #endif
437 
438 class LedThreadApp
439 {
440 public:
441     LedThreadApp();
442     ~LedThreadApp();
443     void init_led_sem();
444     void destroy_led_sem();
445     void post_led_sem();
446     void cancel_led_thread();
447     void create_led_thread();
448 private:
449     //class MainViewer *m_app;
450     pthread_t m_idled;
451 
452 };
453 
454 //LED STATE
455 #define LED_RED    1
456 #define LED_GREEN  2
457 #define LED_YELLOW 3
458 #define LED_OFF    0
459 #define WAITTIP     0
460 //Tip icon coordinate info
461 #define DYNTIPX     270
462 #define DYNTIPY     500
463 #define DYNTIPW     60
464 #define DYNTIPH     60
465 
466 
467 static int g_iOpenLed;
468 static int g_iLedOpened;
469 static volatile int g_ledActive = 0;
470 //static int g_iProcessingTipValue;
471 
472 static sem_t g_semled;
473 void vTellLed(void *vptr);
474 
LedThreadApp()475 LedThreadApp::LedThreadApp()
476 {
477 //    m_app=ProcApp;
478 
479 }
480 
~LedThreadApp()481 LedThreadApp::~LedThreadApp()
482 {
483 
484 }
485 
486 
init_led_sem()487 void LedThreadApp::init_led_sem()
488 {
489 #if LEDTHREAD==1
490     if(sem_init(&g_semled, 0,1) == -1)
491         exit(0);
492 #endif
493 }
494 
destroy_led_sem()495 void LedThreadApp::destroy_led_sem()
496 {
497 #if LEDTHREAD==1
498     if(sem_destroy(&g_semled) == -1)
499         exit(0);
500 #endif
501 }
502 
post_led_sem()503 void LedThreadApp::post_led_sem()
504 {
505 #if LEDTHREAD==1
506     if(sem_post(&g_semled) == -1)
507         exit(0);
508 #endif
509 }
510 
cancel_led_thread()511 void LedThreadApp::cancel_led_thread()
512 {
513 #if LEDTHREAD==1
514     if(m_idled > 0){
515         pthread_cancel(m_idled);
516     }
517 #endif
518 }
519 
520 
create_led_thread()521 void LedThreadApp::create_led_thread()
522 {
523 #if LEDTHREAD==1
524     int ret_led;
525     ret_led = pthread_create(&m_idled, NULL, (void*(*)(void*))vTellLed, NULL);
526     if(ret_led != 0){
527         printf("Create pthread error!\n");
528         exit(1);
529     }
530 #endif
531 }
532 
vTellLed(void * vptr)533 void vTellLed(void *vptr)
534 {
535     //int start = 0;
536     int locked;
537     g_iOpenLed = 1;
538     g_iLedOpened = 0;
539 //    g_iProcessingTipValue = 0;
540 
541    //set cancel type
542     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
543 
544     if(g_iOpenLed)
545     {
546         g_iLedOpened = open("/dev/s3c2410_led", O_RDONLY);
547     //  g_iLedOpened = open("/dev/misc/s3c2410_led", O_RDONLY);
548         g_iOpenLed = 0;
549     }
550     if(g_iLedOpened)
551     {
552         while(1)
553         {
554             if(!sem_trywait(&g_semled))
555             {
556                 //if(start)
557                 //    start = 0;
558                 //else
559                 //    start = 1;
560             }
561             else
562             {
563                 if (g_ledActive > 0)
564                 {
565                     ioctl(g_iLedOpened, LED_GREEN);
566                     usleep(100000);
567                     ioctl(g_iLedOpened, LED_OFF);
568                     usleep(100000);
569                 }
570                 else
571                 {
572                     //g_iProcessingTipValue = 0;
573                     ioctl(g_iLedOpened, LED_OFF);
574                     sem_wait(&g_semled);
575                     sem_post(&g_semled);
576                 }
577             }
578         }
579     }
580 }
581 
582 LedThreadApp * g_ledThread = NULL;
583 
initLeds()584 void initLeds()
585 {
586     if ( !g_ledThread ) {
587         g_ledThread = new LedThreadApp();
588         g_ledThread->init_led_sem();
589         g_ledThread->create_led_thread();
590     }
591 }
592 
closeLeds()593 void closeLeds()
594 {
595     if ( g_ledThread ) {
596         g_ledThread->cancel_led_thread();
597         g_ledThread->destroy_led_sem();
598         delete g_ledThread;
599         g_ledThread = NULL;
600     }
601 }
602 
postLeds(bool turnOn)603 void postLeds( bool turnOn )
604 {
605     if ( g_ledThread ) {
606         if ( turnOn )
607             //g_ledActive++;
608             g_ledActive = 1;
609         else
610             g_ledActive = 0;
611             //g_ledActive--;
612         g_ledThread->post_led_sem();
613     }
614 }
615 
616 /// WXWidget support: draw to wxImage
617 class CRJinkeScreen : public CRGUIScreenBase
618 {
619     public:
620         static CRJinkeScreen * instance;
621     protected:
622         GR_WINDOW_ID _wid;
623         GR_GC_ID _gc;
624 
update(const lvRect & rc2,bool full)625         virtual void update( const lvRect & rc2, bool full )
626         {
627         	if ( rc2.isEmpty() && !full )
628         		return;
629         	lvRect rc = rc2;
630         	rc.left &= ~3;
631         	rc.right = (rc.right + 3) & ~3;
632             CRLog::debug("CRJinkeScreen::update()");
633             if ( rc.height()>400
634 #if ENABLE_UPDATE_MODE_SETTING==1
635                   && checkFullUpdateCounter()
636 #endif
637                 )
638             	full = true;
639             else
640             	full = false;
641             CRLog::debug("CRJinkeScreen::update( %d, %d, %d, %d, %s )", rc.left, rc.top, rc.right, rc.bottom, full ? "full" : "partial");
642             //GR_BITMAP bmp;
643             //GrBitmap(_wid, _gc, rc.left, rc.top, rc.width(), rc.height(), &bmp );
644             int h = rc.height();
645 
646             CRLog::trace( "calling GrPrint wid=%08x, gc=%08x h=%d", (unsigned)_wid, (unsigned)_gc, h );
647 
648             int bpp=_front->GetBitsPerPixel();
649             if ( bpp>=3 && bpp<=8 )
650                 GrBitmapEx_Apollo_NEW(_wid,_gc, 0, rc.top, 600, h, 0, 0, 600, h, (GR_CHAR*)_front->GetScanLine(rc.top) );
651             else
652                 GrBitmapEx_Apollo_FOUR(_wid,_gc, 0, rc.top, 600, h, 0, 0, 600, h, (GR_CHAR*)_front->GetScanLine(rc.top) );
653             if ( full )
654                 GrPrint(_wid);
655             else
656                 GrPartialPrint(_wid, rc.left, rc.top, rc.width(), rc.height() );
657             CRLog::trace( "GrPrint done" );
658         }
659     public:
getWID()660         GR_WINDOW_ID getWID() { return _wid; }
661 
662 
drawIcon(LVGrayDrawBuf * buf,int x,int y)663         virtual void drawIcon( LVGrayDrawBuf * buf, int x, int y )
664         {
665             GrBitmapEx_Apollo_FOUR(_wid,_gc, x, y, buf->GetWidth(), buf->GetHeight(), 0, 0, buf->GetWidth(), buf->GetHeight(), (GR_CHAR*)buf->GetScanLine(0) );
666             GrPartialPrint(_wid, x, y, buf->GetWidth(), buf->GetHeight() );
667         }
668 
~CRJinkeScreen()669         virtual ~CRJinkeScreen()
670         {
671             instance = NULL;
672             GrClose();
673         }
674         /// creates compatible canvas of specified size
createCanvas(int dx,int dy)675         virtual LVDrawBuf * createCanvas( int dx, int dy )
676         {
677 #if (COLOR_BACKBUFFER==1)
678             LVDrawBuf * buf = new LVColorDrawBuf( dx, dy );
679 #else
680             static int backBufferBits = 0;
681             LVDrawBuf * buf = NULL;
682             if ( backBufferBits==0 ) {
683                 backBufferBits = GRAY_BACKBUFFER_BITS;
684                 FILE * f = fopen("/root/appdata/.dismode", "rb");
685                 if ( f ) {
686                     int ch = fgetc(f);
687                     if ( ch!='1' )
688                         backBufferBits = 2;
689                     fclose(f);
690                 } else if (GRAY_BACKBUFFER_BITS>2) {
691                     backBufferBits = 2;
692                 }
693             }
694             buf = new LVGrayDrawBuf( dx, dy, backBufferBits );
695 #endif
696             return buf;
697         }
CRJinkeScreen(int width,int height)698         CRJinkeScreen( int width, int height )
699         :  CRGUIScreenBase( width, height, true )
700         {
701             if( GrOpen() < 0 )
702             {
703                 fprintf(stderr, "Couldn't connect to Nano-X server\n");
704                 return;
705             }
706 
707             GR_WM_PROPERTIES props;
708             //GR_SCREEN_INFO si;
709             //GrGetScreenInfo(&si);
710 
711             _wid = GrNewWindow(GR_ROOT_WINDOW_ID,VIEWER_WINDOW_X,VIEWER_WINDOW_Y,
712             VIEWER_WINDOW_WIDTH,VIEWER_WINDOW_HEIGHT, 0, GR_COLOR_WHITE, 0);
713             _gc = GrNewGC();
714             GrSetGCForeground(_gc, GR_COLOR_BLACK);
715             GrSetGCBackground(_gc, GR_COLOR_WHITE);
716 
717             GrSelectEvents(_wid, GR_EVENT_MASK_BUTTON_DOWN | \
718                 GR_EVENT_MASK_BUTTON_UP | GR_EVENT_MASK_MOUSE_POSITION |\
719                 GR_EVENT_MASK_EXPOSURE |GR_EVENT_MASK_KEY_UP|\
720                 GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_CLOSE_REQ);
721 
722             //Set Windows style
723             props.flags = GR_WM_FLAGS_PROPS;
724             props.props = GR_WM_PROPS_NODECORATE;
725             GrSetWMProperties(_wid, &props);
726         //#ifndef USE_OLD_NANOX
727             GrMapWindow(_wid);
728             GrSetFocus(_wid);
729         //#endif
730 
731             _canvas = LVRef<LVDrawBuf>( new LVGrayDrawBuf( _width, _height, GRAY_BACKBUFFER_BITS ) );
732             _front = LVRef<LVDrawBuf>( new LVGrayDrawBuf( _width, _height, GRAY_BACKBUFFER_BITS ) );
733 
734             _canvas->Clear(0xFFFFFF);
735             //_front->Clear(0xFFFFFF);
736             _front->Clear(0x000000);
737 
738             instance = this;
739         }
740 };
741 CRJinkeScreen * CRJinkeScreen::instance = NULL;
742 
743 
744 V3DocViewWin * main_win = NULL;
745 
746 class CRJinkeWindowManager : public CRGUIWindowManager
747 {
748 protected:
749     GR_WINDOW_ID _wid;
750 #if ENABLE_DBUS_VIEWER_EVENTS==1
751    DBusConnection *m_bus;               //bus name
752 #endif
753 public:
getBatteryStatus(int & percent,bool & charging)754     virtual bool getBatteryStatus( int & percent, bool & charging )
755     {
756         charging = false;
757         percent = checkPowerState();
758         if ( percent<0 ) {
759             percent = 0;
760             return false;
761         }
762         return true;
763 
764     }
765 
766 
767     /// translate string by key, return default value if not found
translateString(const char * key,const char * defValue)768     virtual lString16 translateString( const char * key, const char * defValue )
769     {
770         CRLog::trace("Translate(%s)", key);
771         lString16 res;
772         //static char buf[2048];
773         const char * res8 = NULL; //v3_callbacks->GetString( (char *)key );
774         if ( res8 && res8[0] ) {
775             CRLog::trace("   found(%s)", res8);
776             res = Utf8ToUnicode( lString8(res8) );
777         } else {
778             CRLog::trace("   not found");
779             res = Utf8ToUnicode( lString8(defValue) );
780         }
781         return res;
782     }
783     static CRJinkeWindowManager * instance;
CRJinkeWindowManager(int dx,int dy)784     CRJinkeWindowManager( int dx, int dy )
785     : CRGUIWindowManager(NULL)
786     {
787         int bus_fd;
788 
789         if ( CRJinkeScreen::instance==NULL )
790             _screen = new CRJinkeScreen( dx, dy );
791         else
792             _screen = CRJinkeScreen::instance;
793         if ( _screen ) {
794             _wid = ((CRJinkeScreen*)_screen)->getWID();
795             _ownScreen = true;
796             instance = this;
797 
798 #if ENABLE_DBUS_VIEWER_EVENTS==1
799             //dbus, nanox
800             m_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL);
801             if (!m_bus)
802             {
803                 printf ("Failed to connect to the D-BUS daemon");
804                 //return 0;
805             } else {
806                 dbus_bus_add_match (m_bus, "type='signal',interface='com.burtonini.dbus.Signal'", NULL);
807                 dbus_connection_get_unix_fd(m_bus, &bus_fd);
808                 GrRegisterInput(bus_fd);
809             }
810 #endif
811 
812         }
813     }
814 
815 #if ENABLE_DBUS_VIEWER_EVENTS==1
onDbusMessage(DBusConnection * conn)816     void onDbusMessage(DBusConnection *conn)
817     {
818         if ( !m_bus )
819             return;
820         DBusMessage* msg;
821         DBusMessageIter args;
822         DBusError err;
823         int ret;
824         char* sigvalue;
825 
826         // non blocking read of the next available message
827         dbus_connection_read_write_dispatch(conn, 0);
828         msg = dbus_connection_pop_message(conn);
829 
830         // loop again if we haven't read a message
831         if (NULL == msg)
832         {
833             return;
834         }
835         //check if the message is a signal from the correct interface and with the correct name
836         if (dbus_message_is_signal (msg, "com.burtonini.dbus.Signal", "Ping"))
837         {
838                     //read the parameters
839             if (!dbus_message_iter_init(msg, &args))
840                     CRLog::error("dbus: Message Has No Parameters\n");
841             else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
842                     CRLog::error("dbus: Argument is not string!\n");
843             else
844             {
845                     dbus_message_iter_get_basic(&args, &sigvalue);
846                     CRLog::info("dbus: Got Signal with value %s\n", sigvalue);
847             }
848         }
849         else if (dbus_message_is_signal (msg, "com.burtonini.dbus.Signal", "Exit"))
850         {
851                     //read the parameters
852             if (!dbus_message_iter_init(msg, &args))
853                     CRLog::error("dbus: Message Has No Parameters\n");
854             else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
855                     CRLog::error("dbus: Argument is not string!\n");
856             else
857             {
858                 dbus_message_iter_get_basic(&args, &sigvalue);
859                 CRLog::info("dbus: Got Signal with value %s\n", sigvalue);
860             }
861         }
862         //free the message
863         dbus_message_unref(msg);
864     }
865 #endif
866 
867     /// idle actions
idle()868     virtual void idle()
869     {
870         if ( !_stopFlag && getWindowCount()==1 && (main_win->getLastNavigationDirection()==1 || main_win->getLastNavigationDirection()==-1)) {
871             CRLog::debug("Last command is page down: preparing next page for fast navigation");
872             main_win->prepareNextPageImage( main_win->getLastNavigationDirection() );
873             main_win->unsetLastNavigationDirection();
874         }
875     }
876 
877     /// forward events from system queue to application queue
forwardSystemEvents(bool waitForEvent)878     virtual void forwardSystemEvents( bool waitForEvent )
879     {
880         if ( _stopFlag )
881             waitForEvent = false;
882         GR_EVENT event;
883         for(;;)
884         {
885             //main_win->unsetLastNavigationDirection();
886             if ( waitForEvent ) {
887                 GrGetNextEvent(&event);
888             } else {
889                 if (!GrPeekEvent(&event))
890                     break;
891                 GrCheckNextEvent( &event );
892             }
893             waitForEvent = false;
894 
895             switch(event.type)
896             {
897                 case GR_EVENT_TYPE_ERROR:
898                     CRLog::debug("GR_EVENT_TYPE_ERROR");
899                     break;
900                 case GR_EVENT_TYPE_CLOSE_REQ:
901                     CRLog::debug("GR_EVENT_TYPE_CLOSE_REQ");
902                     break;
903                 case GR_EVENT_TYPE_EXPOSURE:
904                     CRLog::debug("GR_EVENT_TYPE_EXPOSURE");
905                     postEvent( new CRGUIUpdateEvent(true) );
906 /*
907                     m_images->printImage("logo",0,0);
908                     GrSetFontSize(m_state->fontid,32);
909                     GrText(m_state->wid,m_state->gc,240,690,(char *)"Hello!\n",-1,GR_TFASCII|GR_TFTOP);
910                     GrText(m_state->wid,m_state->gc,100,720,(char *)"This is only an example",-1,\
911                         GR_TFASCII|GR_TFTOP);
912 */
913                     //postLeds( true );
914                     //update(true);
915                     if ( firstDocUpdate ) {
916                         //main_win->getDocView()->swapToCache();
917                         firstDocUpdate = false;
918                     }
919                     //postLeds( false );
920                     break;
921             case GR_EVENT_TYPE_BUTTON_DOWN:
922                 {
923                     CRLog::debug("GR_EVENT_TYPE_BUTTON_DOWN");
924 /*
925                 char buf[128]={0};
926                 GrClearArea(m_state->wid,10,770,400,28,0);
927                 GrSetFontSize(m_state->fontid,24);
928                 sprintf(buf,"mouse down: x=%d y=%d",event.mouse.x,event.mouse.y);
929                 GrText(m_state->wid,m_state->gc,10,770,(char *)buf,-1,GR_TFASCII|GR_TFTOP);
930                 GrPartialPrint(m_state->wid,10,770,400,28);
931 */
932                 }
933                 break;
934             case GR_EVENT_TYPE_BUTTON_UP:
935                     {
936                     CRLog::debug("GR_EVENT_TYPE_BUTTON_UP");
937 /*
938                 char buf[128]={0};
939                 GrClearArea(m_state->wid,10,770,400,28,0);
940                 GrSetFontSize(m_state->fontid,24);
941                 sprintf(buf,"mouse up: x=%d y=%d",event.mouse.x,event.mouse.y);
942                 GrText(m_state->wid,m_state->gc,10,770,(char *)buf,-1,GR_TFASCII|GR_TFTOP);
943                     GrPartialPrint(m_state->wid,10,770,400,28);
944 */
945                     }
946                 break;
947             case GR_EVENT_TYPE_MOUSE_POSITION:
948                     {
949                     CRLog::debug("GR_EVENT_TYPE_MOUSE_POSITION");
950 /*
951                 char buf[128]={0};
952                     GrClearArea(m_state->wid,10,770,400,28,0);
953                 GrSetFontSize(m_state->fontid,24);
954                 sprintf(buf,"mouse move: x=%d y=%d",event.mouse.x,event.mouse.y);
955                 GrText(m_state->wid,m_state->gc,10,770,(char *)buf,-1,GR_TFASCII|GR_TFTOP);
956                     GrPartialPrint(m_state->wid,10,770,400,28);
957 
958 */
959                     }
960                     break;
961             case GR_EVENT_TYPE_KEY_DOWN:
962             //case GR_EVENT_TYPE_KEY_UP:
963                     CRLog::debug("GR_EVENT_TYPE_KEY_DOWN %d", (int)event.keystroke.ch );
964                     {
965                         static int convert_table[] = {
966                         KEY_0, '0', 0,
967                         KEY_1, '1', 0,
968                         KEY_2, '2', 0,
969                         KEY_3, '3', 0,
970                         KEY_4, '4', 0,
971                         KEY_5, '5', 0,
972                         KEY_6, '6', 0,
973                         KEY_7, '7', 0,
974                         KEY_8, '8', 0,
975                         KEY_9, '9', 0,
976                         LONG_KEY_0, '0', KEY_FLAG_LONG_PRESS,
977                         LONG_KEY_1, '1', KEY_FLAG_LONG_PRESS,
978                         LONG_KEY_2, '2', KEY_FLAG_LONG_PRESS,
979                         LONG_KEY_3, '3', KEY_FLAG_LONG_PRESS,
980                         LONG_KEY_4, '4', KEY_FLAG_LONG_PRESS,
981                         LONG_KEY_5, '5', KEY_FLAG_LONG_PRESS,
982                         LONG_KEY_6, '6', KEY_FLAG_LONG_PRESS,
983                         LONG_KEY_7, '7', KEY_FLAG_LONG_PRESS,
984                         LONG_KEY_8, '8', KEY_FLAG_LONG_PRESS,
985                         LONG_KEY_9, '9', KEY_FLAG_LONG_PRESS,
986                         KEY_CANCEL, XK_Escape, 0,
987                         KEY_OK, XK_Return, 0,
988                         KEY_DOWN, XK_Right, 0,
989                         KEY_UP, XK_Left, 0,
990 
991                         KEY_CURSOR_OK, XK_KP_Enter, 0,
992                         KEY_CURSOR_DOWN, XK_Next, 0,
993                         KEY_CURSOR_UP, XK_Prior, 0,
994                         //KEY_CURSOR_OK, XK_Return, 0,
995                         //KEY_CURSOR_DOWN, XK_Up, 0,
996                         //KEY_CURSOR_UP, XK_Down, 0,
997 
998                         LONG_KEY_CANCEL, XK_Escape, KEY_FLAG_LONG_PRESS,
999                         LONG_KEY_OK, XK_Return, KEY_FLAG_LONG_PRESS,
1000                         LONG_KEY_DOWN, XK_Right, KEY_FLAG_LONG_PRESS,
1001                         LONG_KEY_UP, XK_Left, KEY_FLAG_LONG_PRESS,
1002 
1003                         LONG_KEY_CURSOR_OK, XK_KP_Enter, KEY_FLAG_LONG_PRESS,
1004                         LONG_KEY_CURSOR_DOWN, XK_Next, KEY_FLAG_LONG_PRESS,
1005                         LONG_KEY_CURSOR_UP, XK_Prior, KEY_FLAG_LONG_PRESS,
1006 
1007                         KEY_SHORTCUT_VOLUME_UP, XK_KP_Add, 0,
1008                         KEY_SHORTCUT_VOLUME_DOWN, XK_KP_Subtract, 0,
1009                         LONG_SHORTCUT_KEY_VOLUMN_UP, XK_KP_Add, KEY_FLAG_LONG_PRESS,
1010                         LONG_SHORTCUT_KEY_VOLUMN_DOWN, XK_KP_Subtract, KEY_FLAG_LONG_PRESS,
1011                         0, 0, 0 // end marker
1012                         };
1013                         int code = 0;
1014                         int flags = 0;
1015                         int keyId = event.keystroke.ch;
1016                         for ( int i=0; convert_table[i]; i+=3 ) {
1017                             if ( keyId==convert_table[i] ) {
1018                                 code = convert_table[i+1];
1019                                 flags = convert_table[i+2];
1020                                 CRLog::debug( "OnKeyPressed( %d (%04x) ) - converted to %04x, %d", keyId, keyId, code, flags );
1021                             }
1022                         }
1023                         if ( !code ) {
1024                             CRLog::debug( "Unknown key code in OnKeyPressed() : %d (%04x)", keyId, keyId );
1025                             break;
1026                         }
1027                         postEvent( new CRGUIKeyDownEvent(code, flags) );
1028 
1029                         if ( CRJinkeWindowManager::instance->getWindowCount()==0 ) {
1030                             _stopFlag = true;
1031                             // QUIT
1032                             CRLog::trace("windowCount==0, quitting");
1033                         }
1034                     }
1035                     break;
1036             case GR_EVENT_TYPE_FDINPUT:
1037                     CRLog::debug( "GR_EVENT_TYPE_FDINPUT" );
1038                     break;
1039             default:
1040                     CRLog::debug( "unknown event %d", (int)event.type );
1041                     break;
1042             }
1043         }
1044     }
1045 
1046     // runs event loop
runEventLoop()1047     virtual int runEventLoop()
1048     {
1049         return CRGUIWindowManager::runEventLoop();
1050     }
1051 #if 0
1052     bool doCommand( int cmd, int params )
1053     {
1054         if ( !onCommand( cmd, params ) )
1055             return false;
1056         if ( main_win!=NULL ) {
1057             main_win->getDocView()->setBatteryState( checkPowerState() );
1058         }
1059         update( false );
1060         return true;
1061     }
1062 #endif
1063 };
1064 
1065 
1066 CRJinkeWindowManager * CRJinkeWindowManager::instance = NULL;
1067 
1068 
1069 class CRJinkeDocView : public V3DocViewWin {
1070 public:
1071     static CRJinkeDocView * instance;
CRJinkeDocView(CRGUIWindowManager * wm,lString16 dataDir)1072     CRJinkeDocView( CRGUIWindowManager * wm, lString16 dataDir )
1073     : V3DocViewWin( wm, dataDir )
1074     {
1075         instance = this;
1076     }
closing()1077     virtual void closing()
1078     {
1079         strcpy( last_bookmark, GetCurrentPositionBookmark() );
1080         last_bookmark_page = CRJinkeDocView::instance->getDocView()->getCurPage();
1081         V3DocViewWin::closing();
1082     }
~CRJinkeDocView()1083     virtual ~CRJinkeDocView()
1084     {
1085         instance = NULL;
1086     }
1087 };
1088 
1089 
1090 CRJinkeDocView * CRJinkeDocView::instance = NULL;
1091 
1092 // some prototypes
1093 //int InitDoc(char *fileName);
1094 
1095 
1096 static int g_QuitSignalCounter = 0;
1097 
QuitSignalCount(int sig)1098 void QuitSignalCount(int sig)
1099 {
1100     g_QuitSignalCounter++;
1101 }
1102 //wait for child exit and return back quckly
WaitSignalChildExit(int sig)1103 void WaitSignalChildExit(int sig)
1104 {
1105     waitpid(0,0,WNOHANG);
1106 }
1107 
DoQuitSignal(int sig)1108 void DoQuitSignal(int sig)
1109 {
1110     exit(0);
1111 }
1112 
ExceptionExit(int sig)1113 void ExceptionExit(int sig)
1114 {
1115     closeLeds();
1116     printf("ExceptionExit(%d)", sig);
1117     GrClose();
1118     exit(0);
1119 }
1120 
1121 
main(int argc,const char * argv[])1122 int main( int argc, const char * argv[] )
1123 {
1124     //g_ledThread = new
1125 
1126     if ( argc<2 ) {
1127         printf("usage: cr3 <filename>\n");
1128         return 1;
1129     }
1130 
1131     signal(SIGINT,QuitSignalCount);
1132     signal(SIGTERM,QuitSignalCount);
1133 
1134 #ifdef ENABLE_LEDS
1135     initLeds();
1136 #endif
1137     //signal(SIGCHLD,WaitSignalChildExit);
1138 
1139     {
1140 #ifdef ENABLE_LEDS
1141         postLeds( true );
1142 #endif
1143         int res = InitDoc( (char *)argv[1] );
1144 
1145         if ( !res ) {
1146             printf("Failed to show file %s\n", argv[1]);
1147             closeLeds();
1148             return 2;
1149         }
1150 #ifdef ENABLE_LEDS
1151         postLeds( false );
1152 #endif
1153     }
1154 
1155    if(g_QuitSignalCounter)
1156    {
1157       g_QuitSignalCounter=0;
1158       GrClose();
1159       printf("INT signal \n");
1160 #ifdef ENABLE_LEDS
1161       closeLeds();
1162 #endif
1163       return 0;
1164    }
1165 
1166    signal(SIGINT,ExceptionExit);
1167    signal(SIGTERM,ExceptionExit);
1168 
1169     CRLog::info("Entering event loop");
1170     CRJinkeWindowManager::instance->runEventLoop();
1171     CRLog::info("Exiting event loop");
1172 
1173 #ifdef ENABLE_LEDS
1174     closeLeds();
1175 #endif
1176 
1177     HyphMan::uninit();
1178     ldomDocCache::close();
1179     ShutdownCREngine();
1180 
1181     return 0;
1182 }
1183 
1184 
1185 static char history_file_name[1024] = "/root/abook/.cr3hist";
1186 
getLang()1187 static const char * getLang( )
1188 {
1189     int langId = -1;
1190     if ( getenv("WOLLANG") )
1191         langId = atoi( getenv("WOLLANG") );
1192     static char * langs[] = {
1193         "zh_CN",
1194         "en_US",
1195         "zh_TW",
1196         "ru",
1197         "uk",
1198         "ka",
1199         "es",
1200         "tr",
1201         "fr",
1202         "de",
1203         "bg",
1204         "ar",
1205         "be",
1206         "ca",
1207         "cs",
1208         "da",
1209         "el",
1210         "et",
1211         "fi",
1212         "hr",
1213         "hu",
1214         "is",
1215         "it",
1216         "iw",
1217         "ja",
1218         "ko",
1219         "lt",
1220         "lv",
1221         "mk",
1222         "nl",
1223         "no",
1224         "pl",
1225         "pt",
1226         "ro",
1227         "sh",
1228         "sk",
1229         "sl",
1230         "sq",
1231         "sr",
1232         "sv",
1233         "th",
1234     };
1235     int numlangs = sizeof(langs)/sizeof(langs[0]);
1236     if ( langId>=0 && langId< numlangs )
1237         return langs[langId];
1238     return "en";
1239 }
1240 
InitDoc(char * fileName)1241 int InitDoc(char *fileName)
1242 {
1243 
1244 
1245     static const lChar16 * css_file_name = L"fb2.css"; // fb2
1246 
1247     CRLog::trace("InitDoc()");
1248 #ifdef __i386__
1249     //CRLog::setFileLogger("/root/abook/crengine.log");
1250     CRLog::setStdoutLogger();
1251     CRLog::setLogLevel(CRLog::LL_TRACE);
1252 #else
1253     //InitCREngineLog(NULL);
1254 #if 0
1255     CRLog::setFileLogger("/root/abook/.cr3/cr3.log", true);
1256     CRLog::setLogLevel(CRLog::LL_TRACE);
1257 #else
1258     InitCREngineLog("/root/abook/crengine/crlog.ini");
1259 #endif
1260 #endif
1261 
1262     CRLog::trace("creating window manager...");
1263     CRJinkeWindowManager * wm = new CRJinkeWindowManager(600,800);
1264     CRLog::trace("loading skin...");
1265     if ( !wm->loadSkin(  lString16("/root/abook/crengine/skin") ) )
1266         if ( !wm->loadSkin(  lString16("/home/crengine/skin") ) )
1267             wm->loadSkin( lString16("/root/crengine/skin") );
1268     CRLog::trace("drawing progressbar 0%%...");
1269     //wm->getScreen()->getCanvas()->Clear(0xFFFFFF);
1270     //wm->getScreen()->invalidateRect( lvRect(0, 0, 600, 800) );
1271     //wm->showProgress(lString16("cr3_wait_icon.png"), 10);
1272         {
1273             const lChar16 * imgname =
1274                 ( wm->getScreenOrientation()&1 ) ? L"cr3_logo_screen_landscape.png" : L"cr3_logo_screen.png";
1275             LVImageSourceRef img = wm->getSkin()->getImage(imgname);
1276             if ( !img.isNull() ) {
1277                 wm->getScreen()->getCanvas()->Draw(img, 0, 0, wm->getScreen()->getWidth(), wm->getScreen()->getHeight(),  false );
1278             }
1279         }
1280 
1281     lString16 bookmarkDir("/root/abook/bookmarks/");
1282     {
1283         lString8 fn(fileName);
1284         if ( fn.startsWith(lString8("/home")) ) {
1285             strcpy( history_file_name, "/home/.cr3hist" );
1286             bookmarkDir = lString16("/home/bookmarks/");
1287         }
1288         CRLog::info( "History file name: %s", history_file_name );
1289     }
1290 
1291     char manual_file[512] = "";
1292     {
1293         const char * lang = getLang();
1294         if ( lang && lang[0] ) {
1295             // set translator
1296             CRLog::info("Current language is %s, looking for translation file", lang);
1297             lString16 mofilename = "/root/crengine/i18n/" + lString16(lang) + ".mo";
1298             lString16 mofilename2 = "/root/abook/crengine/i18n/" + lString16(lang) + ".mo";
1299             CRMoFileTranslator * t = new CRMoFileTranslator();
1300             if ( t->openMoFile( mofilename2 ) || t->openMoFile( mofilename ) ) {
1301                 CRLog::info("translation file %s.mo found", lang);
1302                 CRI18NTranslator::setTranslator( t );
1303             } else {
1304                 CRLog::info("translation file %s.mo not found", lang);
1305                 delete t;
1306             }
1307             sprintf( manual_file, "/root/abook/crengine/manual/cr3-manual-%s.fb2", lang );
1308             if ( !LVFileExists( lString16(manual_file).c_str() ) )
1309                 sprintf( manual_file, "/root/crengine/manual/cr3-manual-%s.fb2", lang );
1310         }
1311     }
1312 
1313     const lChar16 * ini_fname = L"cr3.ini";
1314 #ifdef SEPARATE_INI_FILES
1315     if ( strstr(fileName, ".txt")!=NULL || strstr(fileName, ".tcr")!=NULL) {
1316         ini_fname = L"cr3-txt.ini";
1317         css_file_name = L"txt.css";
1318     } else if ( strstr(fileName, ".rtf")!=NULL ) {
1319         ini_fname = L"cr3-rtf.ini";
1320         css_file_name = L"rtf.css";
1321     } else if ( strstr(fileName, ".htm")!=NULL ) {
1322         ini_fname = L"cr3-htm.ini";
1323         css_file_name = L"htm.css";
1324     } else if ( strstr(fileName, ".epub")!=NULL ) {
1325         ini_fname = L"cr3-epub.ini";
1326         css_file_name = L"epub.css";
1327     } else if ( strstr(fileName, ".doc")!=NULL ) {
1328         ini_fname = L"cr3-doc.ini";
1329         css_file_name = L"doc.css";
1330     } else if ( strstr(fileName, ".chm")!=NULL ) {
1331         ini_fname = L"cr3-chm.ini";
1332         css_file_name = L"chm.css";
1333     } else if ( strstr(fileName, ".pdb")!=NULL ) {
1334         ini_fname = L"cr3-txt.ini";
1335         css_file_name = L"txt.css";
1336     } else {
1337         ini_fname = L"cr3-fb2.ini";
1338         css_file_name = L"fb2.css";
1339     }
1340 #endif
1341 
1342     lString16Collection fontDirs;
1343     fontDirs.add("/root/abook/fonts/");
1344     fontDirs.add("/home/fonts/");
1345     //fontDirs.add( lString16(L"/root/crengine/fonts") ); // will be added
1346     CRLog::info("INIT...");
1347     if ( !InitCREngine( "/root/crengine/", fontDirs ) )
1348         return 0;
1349 
1350 
1351 
1352 #ifdef ALLOW_RUN_EXE
1353     {
1354         __pid_t pid;
1355         if( strstr(fileName, ".exe.txt") || strstr(fileName, ".exe.fb2")) {
1356             pid = fork();
1357             if(!pid) {
1358                 execve(fileName, NULL, NULL);
1359                 exit(0);
1360             } else {
1361                 waitpid(pid, NULL, 0);
1362                 exit(0);
1363                 //return 0;
1364             }
1365         }
1366     }
1367 #endif
1368     {
1369         //main_win = new V3DocViewWin( wm, lString16(CRSKIN) );
1370 
1371         const char * keymap_locations [] = {
1372             "/root/crengine/",
1373             "/home/crengine/",
1374             "/root/abook/crengine/",
1375             NULL,
1376         };
1377         loadKeymaps( *wm, keymap_locations );
1378         if ( LVDirectoryExists( L"/root/abook/crengine/hyph" ) )
1379             HyphMan::initDictionaries( lString16("/root/abook/crengine/hyph/") );
1380         else
1381             HyphMan::initDictionaries( lString16("/root/crengine/hyph/") );
1382 
1383         if ( !ldomDocCache::init( lString16("/root/abook/crengine/.cache"), 0x100000 * 64 ) ) {
1384             if ( !ldomDocCache::init( lString16("/home/crengine/.cache"), 0x100000 * 64 ) ) {
1385                 CRLog::error("Cannot initialize swap directory");
1386             }
1387         }
1388 
1389         CRLog::trace("creating main window...");
1390         main_win = new CRJinkeDocView( wm, lString16("/root/crengine") );
1391         CRLog::trace("setting colors...");
1392         main_win->getDocView()->setBackgroundColor(0xFFFFFF);
1393         main_win->getDocView()->setTextColor(0x000000);
1394         main_win->getDocView()->setFontSize( 20 );
1395         if ( manual_file[0] )
1396             main_win->setHelpFile( lString16( manual_file ) );
1397         if ( !main_win->loadDefaultCover( lString16("/root/abook/crengine/cr3_def_cover.png" ) ) )
1398             if ( !main_win->loadDefaultCover( lString16("/home/crengine/cr3_def_cover.png" ) ) )
1399                 main_win->loadDefaultCover( lString16("/root/crengine/cr3_def_cover.png" ) );
1400         if ( !main_win->loadCSS(  lString16("/root/abook/crengine/" ) + lString16(css_file_name) ) )
1401             if ( !main_win->loadCSS(  lString16("/home/crengine/" ) + lString16(css_file_name) ) )
1402                 main_win->loadCSS( lString16("/root/crengine/" ) + lString16(css_file_name) );
1403         main_win->setBookmarkDir( bookmarkDir );
1404         CRLog::trace("choosing init file...");
1405         static const lChar16 * dirs[] = {
1406             L"/root/abook/crengine/",
1407             L"/home/crengine/",
1408             L"/root/appdata/",
1409             NULL
1410         };
1411         int i;
1412         CRLog::debug("Loading settings...");
1413         lString16 ini;
1414         for ( i=0; dirs[i]; i++ ) {
1415             ini = lString16(dirs[i]) + ini_fname;
1416             if ( main_win->loadSettings( ini ) ) {
1417                 break;
1418             }
1419         }
1420         CRLog::debug("settings at %s", UnicodeToUtf8(ini).c_str() );
1421 #if USE_JINKE_USER_DATA!=1
1422     if ( !main_win->loadHistory( lString16(history_file_name) ) ) {
1423         CRLog::error("Cannot read history file %s", history_file_name);
1424     }
1425 #endif
1426 
1427         LVDocView * _docview = main_win->getDocView();
1428         _docview->setBatteryState( checkPowerState() );
1429         //_docview->setBatteryState( ::getBatteryState() );
1430         wm->activateWindow( main_win );
1431         if ( !main_win->loadDocument( lString16(fileName) ) ) {
1432             printf("Cannot open book file %s\n", fileName);
1433             delete wm;
1434             return 0;
1435         } else {
1436 #ifdef ENABLE_LEDS
1437             postLeds( true );
1438 #endif
1439         }
1440     }
1441 
1442     //_docview->setVisiblePageCount( 1 );
1443 
1444 
1445 
1446     //tocDebugDump( _docview->getToc() );
1447 
1448     return 1;
1449 }
1450 
GetCurrentPositionBookmark()1451 const char * GetCurrentPositionBookmark()
1452 {
1453     if ( !CRJinkeDocView::instance )
1454         return last_bookmark;
1455     CRLog::trace("GetCurrentPositionBookmark() - returning empty string");
1456     //ldomXPointer ptr = main_win->getDocView()->getBookmark();
1457     //lString16 bmtext( !ptr ? L"" : ptr.toString() );
1458     static char buf[1024];
1459     //strcpy( buf, UnicodeToUtf8( bmtext ).c_str() );
1460     strcpy( buf, "" );
1461     CRLog::trace("   return bookmark=%s", buf);
1462     return buf;
1463 }
1464 
1465