zoukankan      html  css  js  c++  java
  • 电子书总结

    参考:https://blog.csdn.net/qq_21792169/article/details/51052666

    1.框架

    链接:https://pan.baidu.com/s/1qn0kP3zGUdU6VVtL8GWQTQ
    提取码:mwwe

    2.文件管理

    工程目录结构:

    include头文件目录:

    包含所有头文件

    config.h为配置文件

    #ifndef _CONFIG_H
    #define _CONFIG_H
    
    #include <stdio.h>
    #include <debug_manager.h>
    
    #define FB_DEVICE_NAME "/dev/fb0"
    
    #define COLOR_BACKGROUND   0xE7DBB5  /* 泛黄的纸 */
    #define COLOR_FOREGROUND   0x514438  /* 褐色字体 */
    
    //#define DBG_PRINTF(...)  
    #define DBG_PRINTF DebugPrint
    
    #endif /* _CONFIG_H */
    

    其中Makefile为:https://www.cnblogs.com/huangdengtao/p/12324579.html

    3.流程图

    我只画了一些。

    链接:https://pan.baidu.com/s/1XpkjpMV8ztXE9kwxYODCLA
    提取码:m31u

    链接:https://pan.baidu.com/s/15MQXs7nPHUCQaXjEk0QxNA
    提取码:4fba

    4.各个模块的具体分析

    display模块(display目录)

    Makefile

    obj-y += disp_manager.o
    obj-y += fb.o
    

    display_manager.h

    #ifndef _DISP_MANAGER_H
    #define _DISP_MANAGER_H
    
    typedef struct DispOpr {
    	char *name;
    	int iXres;
    	int iYres;
    	int iBpp;
    	int (*DeviceInit)(void);
    	int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);
    	int (*CleanScreen)(unsigned int dwBackColor);
    	struct DispOpr *ptNext;
    }T_DispOpr, *PT_DispOpr;
    
    int RegisterDispOpr(PT_DispOpr ptDispOpr); // 注册链表
    void ShowDispOpr(void);                    // 打印链表中的每个name
    int DisplayInit(void);                     // fb设备注册金链表
    int FBInit(void);                          // 把结构体注册到链表
    
    #endif /* _DISP_MANAGER_H */
    

    display_manager.c

    #include <config.h>
    #include <disp_manager.h>
    #include <string.h>
    
    static PT_DispOpr g_ptDispOprHead;        // 链表头
    
    int RegisterDispOpr(PT_DispOpr ptDispOpr)
    {
    	PT_DispOpr ptTmp;
    
    	if (!g_ptDispOprHead)
    	{
    		g_ptDispOprHead   = ptDispOpr;
    		ptDispOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptDispOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	  = ptDispOpr;
    		ptDispOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowDispOpr(void)
    {
    	int i = 0;
    	PT_DispOpr ptTmp = g_ptDispOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    /*    根据name在链表中查找匹配的链表    */
    PT_DispOpr GetDispOpr(char *pcName)        
    {
    	PT_DispOpr ptTmp = g_ptDispOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    int DisplayInit(void)
    {
    	int iError;
    	
    	iError = FBInit();
    
    	return iError;
    }
    

    fb.c

    /*    这里是具体的设备的初始化了    */
    #include <config.h>
    #include <disp_manager.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <linux/fb.h>
    #include <string.h>
    
    /*    函数声明,用来初始化结构体中的成员函数    */
    static int FBDeviceInit(void);
    static int FBShowPixel(int iX, int iY, unsigned int dwColor);
    static int FBCleanScreen(unsigned int dwBackColor);
    
    
    static int g_fd;
    
    static struct fb_var_screeninfo g_tFBVar;
    static struct fb_fix_screeninfo g_tFBFix;			
    static unsigned char *g_pucFBMem;
    static unsigned int g_dwScreenSize;
    
    static unsigned int g_dwLineWidth;
    static unsigned int g_dwPixelWidth;
    
    static T_DispOpr g_tFBOpr = {
    	.name        = "fb",
    	.DeviceInit  = FBDeviceInit,
    	.ShowPixel   = FBShowPixel,
    	.CleanScreen = FBCleanScreen,
    };
    
    static int FBDeviceInit(void)
    {
    	int ret;
    	
        /*    FB_DEVICE_NAME在配置文件中已经声明    */
    	g_fd = open(FB_DEVICE_NAME, O_RDWR);
    	if (0 > g_fd)
    	{
    		DBG_PRINTF("can't open %s
    ", FB_DEVICE_NAME);
    	}
    
    	ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
    	if (ret < 0)
    	{
    		DBG_PRINTF("can't get fb's var
    ");
    		return -1;
    	}
    
    	ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
    	if (ret < 0)
    	{
    		DBG_PRINTF("can't get fb's fix
    ");
    		return -1;
    	}
    	
    	g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
    	g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
    	if (0 > g_pucFBMem)	
    	{
    		DBG_PRINTF("can't mmap
    ");
    		return -1;
    	}
    
    	g_tFBOpr.iXres       = g_tFBVar.xres;
    	g_tFBOpr.iYres       = g_tFBVar.yres;
    	g_tFBOpr.iBpp        = g_tFBVar.bits_per_pixel;
    
    	g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
    	g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
    	
    	return 0;
    }
    
    
    static int FBShowPixel(int iX, int iY, unsigned int dwColor)
    {
    	unsigned char *pucFB;
    	unsigned short *pwFB16bpp;
    	unsigned int *pdwFB32bpp;
    	unsigned short wColor16bpp; /* 565 */
    	int iRed;
    	int iGreen;
    	int iBlue;
    
    	if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
    	{
    		DBG_PRINTF("out of region
    ");
    		return -1;
    	}
    
    	pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
    	pwFB16bpp  = (unsigned short *)pucFB;
    	pdwFB32bpp = (unsigned int *)pucFB;
    	
    	switch (g_tFBVar.bits_per_pixel)
    	{
    		case 8:
    		{
    			*pucFB = (unsigned char)dwColor;
    			break;
    		}
    		case 16:
    		{
    			iRed   = (dwColor >> (16+3)) & 0x1f;
    			iGreen = (dwColor >> (8+2)) & 0x3f;
    			iBlue  = (dwColor >> 3) & 0x1f;
    			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
    			*pwFB16bpp	= wColor16bpp;
    			break;
    		}
    		case 32:
    		{
    			*pdwFB32bpp = dwColor;
    			break;
    		}
    		default :
    		{
    			DBG_PRINTF("can't support %d bpp
    ", g_tFBVar.bits_per_pixel);
    			return -1;
    		}
    	}
    
    	return 0;
    }
    /*    注意这里16bpp和32bpp清屏时时一位一位的清    */
    static int FBCleanScreen(unsigned int dwBackColor)
    {
    	unsigned char *pucFB;
    	unsigned short *pwFB16bpp;
    	unsigned int *pdwFB32bpp;
    	unsigned short wColor16bpp; /* 565 */
    	int iRed;
    	int iGreen;
    	int iBlue;
    	int i = 0;
    
    	pucFB      = g_pucFBMem;
    	pwFB16bpp  = (unsigned short *)pucFB;
    	pdwFB32bpp = (unsigned int *)pucFB;
    
    	switch (g_tFBVar.bits_per_pixel)
    	{
    		case 8:
    		{
    			memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
    			break;
    		}
    		case 16:
    		{
    			iRed   = (dwBackColor >> (16+3)) & 0x1f;
    			iGreen = (dwBackColor >> (8+2)) & 0x3f;
    			iBlue  = (dwBackColor >> 3) & 0x1f;
    			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
    			while (i < g_dwScreenSize)
    			{
    				*pwFB16bpp	= wColor16bpp;
    				pwFB16bpp++;
    				i += 2;
    			}
    			break;
    		}
    		case 32:
    		{
    			while (i < g_dwScreenSize)
    			{
    				*pdwFB32bpp	= dwBackColor;
    				pdwFB32bpp++;
    				i += 4;
    			}
    			break;
    		}
    		default :
    		{
    			DBG_PRINTF("can't support %d bpp
    ", g_tFBVar.bits_per_pixel);
    			return -1;
    		}
    	}
    
    	return 0;
    }
    
    /*    把结构体注册到链表    */
    int FBInit(void)        
    {
    	return RegisterDispOpr(&g_tFBOpr);
    }
    

    font模块(fonts目录)

    Makefile

    obj-y += ascii.o
    obj-y += fonts_manager.o
    obj-y += freetype.o
    obj-y += gbk.o
    

    fonts_manager.h

    #ifndef _FONTS_MANAGER_H
    #define _FONTS_MANAGER_H
    
    typedef struct FontBitMap {
    	int iXLeft;
    	int iYTop;
    	int iXMax;
    	int iYMax;
    	int iBpp;
    	int iPitch;   /* 对于单色位图, 两行象素之间的跨度 */
    	int iCurOriginX;
    	int iCurOriginY;
    	int iNextOriginX;
    	int iNextOriginY;
    	unsigned char *pucBuffer;
    }T_FontBitMap, *PT_FontBitMap;
    
    typedef struct FontOpr {
    	char *name;
    	int (*FontInit)(char *pcFontFile, unsigned int dwFontSize);
    	int (*GetFontBitmap)(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    	struct FontOpr *ptNext;
    }T_FontOpr, *PT_FontOpr;
    
    
    int RegisterFontOpr(PT_FontOpr ptFontOpr);
    void ShowFontOpr(void);
    int FontsInit(void);        // 初始化ASCIIIni(void), GBKInit(void), FreeTypeInit(void)
    int ASCIIInit(void);
    int GBKInit(void);
    int FreeTypeInit(void);
    PT_FontOpr GetFontOpr(char *pcName);
    
    #endif /* _FONTS_MANAGER_H */
    

    fonts_manager.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <string.h>
    
    static PT_FontOpr g_ptFontOprHead = NULL;
    
    int RegisterFontOpr(PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptTmp;
    
    	if (!g_ptFontOprHead)
    	{
    		g_ptFontOprHead   = ptFontOpr;
    		ptFontOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptFontOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext     = ptFontOpr;
    		ptFontOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowFontOpr(void)
    {
    	int i = 0;
    	PT_FontOpr ptTmp = g_ptFontOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_FontOpr GetFontOpr(char *pcName)
    {
    	PT_FontOpr ptTmp = g_ptFontOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    
    int FontsInit(void)
    {
    	int iError;
    	
    	iError = ASCIIInit();
    	if (iError)
    	{
    		DBG_PRINTF("ASCIIInit error!
    ");
    		return -1;
    	}
    
    	iError = GBKInit();
    	if (iError)
    	{
    		DBG_PRINTF("GBKInit error!
    ");
    		return -1;
    	}
    	
    	iError = FreeTypeInit();
    	if (iError)
    	{
    		DBG_PRINTF("FreeTypeInit error!
    ");
    		return -1;
    	}
    
    	return 0;
    }
    

    asiic.c

    #include <config.h>
    #include <fonts_manager.h>
    
    #define FONTDATAMAX 4096
    
    static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tASCIIFontOpr = {
    	.name          = "ascii",
    	.FontInit      = ASCIIFontInit,
    	.GetFontBitmap = ASCIIGetFontBitmap,
    };
    
    
    static const unsigned char fontdata_8x16[FONTDATAMAX] = {
    /*    英文点阵(略)    */
    };
    
    static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	if (dwFontSize != 16)
    	{
    		//DBG_PRINTF("ASCII can't support %d font size
    ", dwFontSize);
    		return -1;
    	}
    	return 0;
    }
    
    /*    编码的位图转化为字体的位图    */
    static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    	
    	if (dwCode > (unsigned int)0x80)
    	{
    		//DBG_PRINTF("don't support this code : 0x%x
    ", dwCode);
    		return -1;
    	}
    
    	ptFontBitMap->iXLeft    = iPenX;
    	ptFontBitMap->iYTop     = iPenY - 16;
    	ptFontBitMap->iXMax     = iPenX + 8;
    	ptFontBitMap->iYMax     = iPenY;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = 1;
    	ptFontBitMap->pucBuffer = (unsigned char *)&fontdata_8x16[dwCode * 16];;	
    
    	ptFontBitMap->iNextOriginX = iPenX + 8;
    	ptFontBitMap->iNextOriginY = iPenY;
    	
    	return 0;
    }
    
    int ASCIIInit(void)
    {
    	return RegisterFontOpr(&g_tASCIIFontOpr);
    }
    

    gbk.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <unistd.h>
    
    
    static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tGBKFontOpr = {
    	.name          = "gbk",
    	.FontInit      = GBKFontInit,
    	.GetFontBitmap = GBKGetFontBitmap,
    };
    
    static int g_iFdHZK;
    static unsigned char *g_pucHZKMem;
    static unsigned char *g_pucHZKMemEnd;
    
    static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	struct stat tStat;
    
    	if (16 != dwFontSize)
    	{
    		DBG_PRINTF("GBK can't support %d fontsize
    ", dwFontSize);
    		return -1;
    	}
    	
    	g_iFdHZK = open(pcFontFile, O_RDONLY);
    	if (g_iFdHZK < 0)
    	{
    		DBG_PRINTF("can't open %s
    ", pcFontFile);
    		return -1;
    	}
    	if(fstat(g_iFdHZK, &tStat))
    	{
    		DBG_PRINTF("can't get fstat
    ");
    		return -1;
    	}
    	g_pucHZKMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdHZK, 0);
    	if (g_pucHZKMem == (unsigned char *)-1)
    	{
    		DBG_PRINTF("can't mmap for hzk16
    ");
    		return -1;
    	}
    	g_pucHZKMemEnd = g_pucHZKMem + tStat.st_size;
    	return 0;
    }
    
    static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iArea;
    	int iWhere;
    
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    	if (dwCode & 0xffff0000)
    	{
    		DBG_PRINTF("don't support this code : 0x%x
    ", dwCode);
    		return -1;
    	}	
    
    	iArea  = (int)(dwCode & 0xff) - 0xA1;
    	iWhere = (int)((dwCode >> 8) & 0xff) - 0xA1;
    
    	if ((iArea < 0) || (iWhere < 0))
    	{
    		DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    		return -1;
    	}
    	
    	ptFontBitMap->iXLeft    = iPenX;
    	ptFontBitMap->iYTop     = iPenY - 16;
    	ptFontBitMap->iXMax     = iPenX + 16;
    	ptFontBitMap->iYMax     = iPenY;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = 2;
    	ptFontBitMap->pucBuffer = g_pucHZKMem + (iArea * 94 + iWhere)*32;;	
    
    	if (ptFontBitMap->pucBuffer >= g_pucHZKMemEnd)
    	{
    		return -1;
    	}
    
    	ptFontBitMap->iNextOriginX = iPenX + 16;
    	ptFontBitMap->iNextOriginY = iPenY;
    	
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	return 0;
    }
    
    int GBKInit(void)
    {
    	return RegisterFontOpr(&g_tGBKFontOpr);
    }
    

    freetype.c

    #include <config.h>
    #include <fonts_manager.h>
    #include <ft2build.h>
    #include FT_FREETYPE_H
    #include FT_GLYPH_H
    
    static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize);
    static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
    
    static T_FontOpr g_tFreeTypeFontOpr = {
    	.name          = "freetype",
    	.FontInit      = FreeTypeFontInit,
    	.GetFontBitmap = FreeTypeGetFontBitmap,
    };
    
    static FT_Library g_tLibrary;
    static FT_Face g_tFace;
    static FT_GlyphSlot g_tSlot;
    
    static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize)
    {
    	int iError;
    
    	/* 显示矢量字体 */
    	iError = FT_Init_FreeType(&g_tLibrary );			   /* initialize library */
    	/* error handling omitted */
    	if (iError)
    	{
    		DBG_PRINTF("FT_Init_FreeType failed
    ");
    		return -1;
    	}
    	
    	iError = FT_New_Face(g_tLibrary, pcFontFile, 0, &g_tFace); /* create face object */
    	/* error handling omitted */
    	if (iError)
    	{
    		DBG_PRINTF("FT_Init_FreeType failed
    ");		
    		return -1;
    	}
    	
    	g_tSlot = g_tFace->glyph;
    
    	iError = FT_Set_Pixel_Sizes(g_tFace, dwFontSize, 0);
    	if (iError)
    	{
    		DBG_PRINTF("FT_Set_Pixel_Sizes failed : %d
    ", dwFontSize);
    		return -1;
    	}
    	
    	
    	return 0;
    }
    
    static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
    {
    	int iError;
    	int iPenX = ptFontBitMap->iCurOriginX;
    	int iPenY = ptFontBitMap->iCurOriginY;
    #if 0
    	FT_Vector tPen;
    
    	tPen.x = 0;
    	tPen.y = 0;
    	
    	/* set transformation */
    	FT_Set_Transform(g_tFace, 0, &tPen);
    #endif
    
    	/* load glyph image into the slot (erase previous one) */
    	//iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER );
    	iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
    	if (iError)
    	{
    		DBG_PRINTF("FT_Load_Char error for code : 0x%x
    ", dwCode);
    		return -1;
    	}
    
    	//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d
    ", iPenX, iPenY, g_tSlot->bitmap_left, g_tSlot->bitmap_top, g_tSlot->bitmap.width, g_tSlot->bitmap.rows);
    	ptFontBitMap->iXLeft    = iPenX + g_tSlot->bitmap_left;
    	ptFontBitMap->iYTop     = iPenY - g_tSlot->bitmap_top;
    	ptFontBitMap->iXMax     = ptFontBitMap->iXLeft + g_tSlot->bitmap.width;
    	ptFontBitMap->iYMax     = ptFontBitMap->iYTop  + g_tSlot->bitmap.rows;
    	ptFontBitMap->iBpp      = 1;
    	ptFontBitMap->iPitch    = g_tSlot->bitmap.pitch;
    	ptFontBitMap->pucBuffer = g_tSlot->bitmap.buffer;
    	
    	ptFontBitMap->iNextOriginX = iPenX + g_tSlot->advance.x / 64;
    	ptFontBitMap->iNextOriginY = iPenY;
    
    	//DBG_PRINTF("iXLeft = %d, iYTop = %d, iXMax = %d, iYMax = %d, iNextOriginX = %d, iNextOriginY = %d
    ", ptFontBitMap->iXLeft, ptFontBitMap->iYTop, ptFontBitMap->iXMax, ptFontBitMap->iYMax, ptFontBitMap->iNextOriginX, ptFontBitMap->iNextOriginY);
    
    	return 0;
    }
    
    int FreeTypeInit(void)
    {
    	return RegisterFontOpr(&g_tFreeTypeFontOpr);
    }
    

    enconding模块(enconding目录)

    Makefile

    obj-y += ascii.o
    obj-y += encoding_manager.o
    obj-y += utf-16be.o
    obj-y += utf-16le.o
    obj-y += utf-8.o
    

    enconding_manager.h

    #ifndef _ENCODING_MANAGER_H
    #define _ENCODING_MANAGER_H
    
    #include <fonts_manager.h>
    #include <disp_manager.h>
    
    typedef struct EncodingOpr {
    	char *name;
    	int iHeadLen;            // 头部的长度
    	PT_FontOpr ptFontOprSupportedHead;        // 
    	int (*isSupport)(unsigned char *pucBufHead);        // 支持
    	int (*GetCodeFrmBuf)(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);    // 得到编码
    	struct EncodingOpr *ptNext;
    }T_EncodingOpr, *PT_EncodingOpr;
    
    int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr);
    void ShowEncodingOpr(void);
    PT_DispOpr GetDispOpr(char *pcName);
    PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead);        // 根据文件的头部编码在链表中寻找匹配的字形编码
    int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
    int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
    int EncodingInit(void);
    int AsciiEncodingInit(void);
    int  Utf16beEncodingInit(void);
    int  Utf16leEncodingInit(void);
    int  Utf8EncodingInit(void);
    
    #endif /* _ENCODING_MANAGER_H */
    

    enconding_manager.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    #include <stdlib.h>
    
    static PT_EncodingOpr g_ptEncodingOprHead;
    
    int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr)
    {
    	PT_EncodingOpr ptTmp;
    
    	if (!g_ptEncodingOprHead)
    	{
    		g_ptEncodingOprHead   = ptEncodingOpr;
    		ptEncodingOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptEncodingOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	      = ptEncodingOpr;
    		ptEncodingOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    
    void ShowEncodingOpr(void)
    {
    	int i = 0;
    	PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead)
    {
    	PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
    
    	while (ptTmp)
    	{	
    		if (ptTmp->isSupport(pucFileBufHead))
    			return ptTmp;
    		else
    			ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    /*    在链表中加入每个编码支持的字形    */
    int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptFontOprCpy;
    	
    	if (!ptEncodingOpr || !ptFontOpr)
    	{
    		return -1;
    	}
    	else
    	{
    		ptFontOprCpy = malloc(sizeof(T_FontOpr));
    		if (!ptFontOprCpy)
    		{
    			return -1;
    		}
    		else
    		{
    			memcpy(ptFontOprCpy, ptFontOpr, sizeof(T_FontOpr));
    			ptFontOprCpy->ptNext = ptEncodingOpr->ptFontOprSupportedHead;
    			ptEncodingOpr->ptFontOprSupportedHead = ptFontOprCpy;
    			return 0;
    		}		
    	}
    }
    
    /*    在链表中删除每个编码支持的字形    */
    int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
    {
    	PT_FontOpr ptTmp;
    	PT_FontOpr ptPre;
    		
    	if (!ptEncodingOpr || !ptFontOpr)
    	{
    		return -1;
    	}
    	else
    	{
    		ptTmp = ptEncodingOpr->ptFontOprSupportedHead;
    		if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
    		{
    			/* 删除头节点 */
    			ptEncodingOpr->ptFontOprSupportedHead = ptTmp->ptNext;
    			free(ptTmp);
    			return 0;
    		}
    
    		ptPre = ptEncodingOpr->ptFontOprSupportedHead;
    		ptTmp = ptPre->ptNext;
    		while (ptTmp)
    		{
    			if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
    			{
    				/* 从链表里取出、释放 */
    				ptPre->ptNext = ptTmp->ptNext;
    				free(ptTmp);
    				return 0;
    			}
    			else
    			{
    				ptPre = ptTmp;
    				ptTmp = ptTmp->ptNext;
    			}
    		}
    
    		return -1;
    	}
    }
    
    int EncodingInit(void)
    {
    	int iError;
    
    	iError = AsciiEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("AsciiEncodingInit error!
    ");
    		return -1;
    	}
    
    	iError = Utf16leEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf16leEncodingInit error!
    ");
    		return -1;
    	}
    	
    	iError = Utf16beEncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf16beEncodingInit error!
    ");
    		return -1;
    	}
    	
    	iError = Utf8EncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("Utf8EncodingInit error!
    ");
    		return -1;
    	}
    
    	return 0;
    }
    

    asiic.c(具体的编码文件)

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isAsciiCoding(unsigned char *pucBufHead);
    static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tAsciiEncodingOpr = {
    	.name          = "ascii",
    	.iHeadLen      = 0,
    	.isSupport     = isAsciiCoding,
    	.GetCodeFrmBuf = AsciiGetCodeFrmBuf,
    };
    
    static int isAsciiCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf8[]    = {0xEF, 0xBB, 0xBF, 0};
    	const char aStrUtf16le[] = {0xFF, 0xFE, 0};
    	const char aStrUtf16be[] = {0xFE, 0xFF, 0};
    	
    	if (strncmp((const char*)pucBufHead, aStrUtf8, 3) == 0)
    	{
    		/* UTF-8 */
    		return 0;
    	}
    	else if (strncmp((const char*)pucBufHead, aStrUtf16le, 2) == 0)
    	{
    		/* UTF-16 little endian */
    		return 0;
    	}
    	else if (strncmp((const char*)pucBufHead, aStrUtf16be, 2) == 0)
    	{
    		/* UTF-16 big endian */
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    
    /*    Get字的编码    */
    static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	unsigned char *pucBuf = pucBufStart;
    	unsigned char c = *pucBuf;
    	
        /* 当判断出来不支持UTF-8,UTF-16Be和UTF-16le后。还需要判断为asiic值还是GBK码
         * (pucBuf < pucBufEnd) && (c < (unsigned char)0x80):判断为asiic值
         * ((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80):判断为GBK码。注:因为GBK码为2字节所以这里需要加1
         */
    	if ((pucBuf < pucBufEnd) && (c < (unsigned char)0x80))
    	{
    		/* 返回ASCII码 */
    		*pdwCode = (unsigned int)c;
    		return 1;
    	}
    
    	if (((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80))
    	{
    		/* 返回GBK码 */
    		*pdwCode = pucBuf[0] + (((unsigned int)pucBuf[1])<<8);
    		return 2;
    	}
    
    	if (pucBuf < pucBufEnd)
    	{
    		/* 可能文件有损坏, 但是还是返回一个码, 即使它是错误的 */
    		*pdwCode = (unsigned int)c;
    		return 1;
    	}
    	else
    	{
    		/* 文件处理完毕 */
    		return 0;
    	}
    }
    
    /*    使当前编码支持freetype, ascii, gbk字形。同时注册链表    */
    int AsciiEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("ascii"));
    	AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("gbk"));
    	return RegisterEncodingOpr(&g_tAsciiEncodingOpr);
    }
    

    utf-8.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf8Coding(unsigned char *pucBufHead);
    static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf8EncodingOpr = {
    	.name          = "utf-8",
    	.iHeadLen	   = 3,
    	.isSupport     = isUtf8Coding,
    	.GetCodeFrmBuf = Utf8GetCodeFrmBuf,
    };
    
    static int isUtf8Coding(unsigned char *pucBufHead)
    {
    	const char aStrUtf8[]    = {0xEF, 0xBB, 0xBF, 0};
    	if (strncmp((const char*)pucBufHead, aStrUtf8, 3) == 0)
    	{
    		/* UTF-8 */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    /* 获得前导为1的位的个数
    * 比如二进制数 11001111 的前导1有2位
    *              11100001 的前导1有3位
    */
    static int GetPreOneBits(unsigned char ucVal)
    {
    	int i;
    	int j = 0;
    	
    	for (i = 7; i >= 0; i--)
    	{
    		if (!(ucVal & (1<<i)))
    			break;
    		else
    			j++;
    	}
    	return j;
    
    }
    
    static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    #if 0
    	对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
    	如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
    	如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
    	如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
    	如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;
    
    	因此,对UTF-8编码中的任意字节,根据第一位,可判断是否为ASCII字符;
    	根据前二位,可判断该字节是否为一个字符编码的第一个字节; 
    	根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;
    	根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。
    #endif
    
    	int i;	
    	int iNum;
    	unsigned char ucVal;
    	unsigned int dwSum = 0;
    
    	if (pucBufStart >= pucBufEnd)
    	{
    		/* 文件结束 */
    		return 0;
    	}
        /*    注意下面的构造    */
    	ucVal = pucBufStart[0];
    	iNum  = GetPreOneBits(pucBufStart[0]);
    
    	if ((pucBufStart + iNum) > pucBufEnd)
    	{
    		/* 文件结束 */
    		return 0;
    	}
    
    	if (iNum == 0)
    	{
    		/* ASCII */
    		*pdwCode = pucBufStart[0];
    		return 1;
    	}
    	else
    	{
    		ucVal = ucVal << iNum;
    		ucVal = ucVal >> iNum;
    		dwSum += ucVal;
    		for (i = 1; i < iNum; i++)
    		{
    			ucVal = pucBufStart[i] & 0x3f;
    			dwSum = dwSum << 6;
    			dwSum += ucVal;			
    		}
    		*pdwCode = dwSum;
    		return iNum;
    	}
    }
    
    int  Utf8EncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf8EncodingOpr);
    }
    

    utf-16be.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf16beCoding(unsigned char *pucBufHead);
    static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf16beEncodingOpr = {
    	.name          = "utf-16be",
    	.iHeadLen	   = 2,
    	.isSupport     = isUtf16beCoding,
    	.GetCodeFrmBuf = Utf16beGetCodeFrmBuf,
    };
    
    /*    用两字节表示一个字:注意大字节序和小字节序    */
    static int isUtf16beCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf16be[] = {0xFE, 0xFF, 0};
    	
    	if (strncmp((const char*)pucBufHead, aStrUtf16be, 2) == 0)
    	{
    		/* UTF-16 big endian */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	if (pucBufStart + 1 < pucBufEnd)
    	{
    		*pdwCode = (((unsigned int)pucBufStart[0])<<8) + pucBufStart[1];
    		return 2;
    	}
    	else
    	{
    		/* 文件结束 */
    		return 0;
    	}
    }
    
    int  Utf16beEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf16beEncodingOpr);
    }
    

    utf-16le.c

    #include <config.h>
    #include <encoding_manager.h>
    #include <string.h>
    
    static int isUtf16leCoding(unsigned char *pucBufHead);
    static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
    
    static T_EncodingOpr g_tUtf16leEncodingOpr = {
    	.name          = "utf-16le",
    	.iHeadLen	   = 2,
    	.isSupport     = isUtf16leCoding,
    	.GetCodeFrmBuf = Utf16leGetCodeFrmBuf,
    };
    
    static int isUtf16leCoding(unsigned char *pucBufHead)
    {
    	const char aStrUtf16le[] = {0xFF, 0xFE, 0};
    	if (strncmp((const char *)pucBufHead, aStrUtf16le, 2) == 0)
    	{
    		/* UTF-16 little endian */
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
    {
    	if (pucBufStart + 1 < pucBufEnd)
    	{
    		*pdwCode = (((unsigned int)pucBufStart[1])<<8) + pucBufStart[0];
    		return 2;
    	}
    	else
    	{
    		/* 文件结束 */
    		return 0;
    	}
    }
    
    int  Utf16leEncodingInit(void)
    {
    	AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("freetype"));
    	AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("ascii"));
    	return RegisterEncodingOpr(&g_tUtf16leEncodingOpr);
    }
    

    input模块(input目录)

    Makefile

    obj-y += input_manager.o
    obj-y += stdin.o
    obj-y += touchscreen.o
    

    input_manager.h

    #ifndef _INPUT_MANAGER_H
    #define _INPUT_MANAGER_H
    #include <sys/time.h>
    #include <pthread.h>
    
    #define INPUT_TYPE_STDIN        0
    #define INPUT_TYPE_TOUCHSCREEN  1
    
    #define INPUT_VALUE_UP          0   
    #define INPUT_VALUE_DOWN        1
    #define INPUT_VALUE_EXIT        2
    #define INPUT_VALUE_UNKNOWN     -1
    
    
    typedef struct InputEvent {
    	struct timeval tTime;
    	int iType;  /* stdin, touchsceen */
    	int iVal;   /*  */
    }T_InputEvent, *PT_InputEvent;
    
    
    typedef struct InputOpr {
    	char *name;
    	pthread_t tTreadID;            // 线程ID
    	int (*DeviceInit)(void);
    	int (*DeviceExit)(void);
    	int (*GetInputEvent)(PT_InputEvent ptInputEvent);
    	struct InputOpr *ptNext;
    }T_InputOpr, *PT_InputOpr;
    
    
    int InputInit(void);
    int RegisterInputOpr(PT_InputOpr ptInputOpr);
    void ShowInputOpr(void);
    int AllInputDevicesInit(void);
    int GetInputEvent(PT_InputEvent ptInputEvent);
    
    int StdinInit(void);
    int TouchScreenInit(void);
    
    #endif /* _INPUT_MANAGER_H */
    

    input_manager.c

    #include <config.h>
    #include <input_manager.h>
    #include <string.h>
    
    static PT_InputOpr g_ptInputOprHead;        // PT_InputOpr结构体
    static T_InputEvent g_tInputEvent;          // T_InputEvent 结构体
    
    static pthread_mutex_t g_tMutex  = PTHREAD_MUTEX_INITIALIZER;        // 互斥锁
    static pthread_cond_t  g_tConVar = PTHREAD_COND_INITIALIZER;         // 条件变量
    
    int RegisterInputOpr(PT_InputOpr ptInputOpr)
    {
    	PT_InputOpr ptTmp;
    
    	if (!g_ptInputOprHead)
    	{
    		g_ptInputOprHead   = ptInputOpr;
    		ptInputOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptInputOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	  = ptInputOpr;
    		ptInputOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowInputOpr(void)
    {
    	int i = 0;
    	PT_InputOpr ptTmp = g_ptInputOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    /*    线程函数    */
    static void *InputEventTreadFunction(void *pVoid)
    {
    	T_InputEvent tInputEvent;
    	
    	/* 定义函数指针 */
    	int (*GetInputEvent)(PT_InputEvent ptInputEvent);
    	GetInputEvent = (int (*)(PT_InputEvent))pVoid;
    
    	while (1)
    	{
    		if(0 == GetInputEvent(&tInputEvent))
    		{
    			/* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 */
    			/* 访问临界资源前,先获得互斥量 */
            /*    上锁    */
    			pthread_mutex_lock(&g_tMutex);
    			g_tInputEvent = tInputEvent;
    
    			/*  唤醒主线程 */
    			pthread_cond_signal(&g_tConVar);
    
    			/* 释放互斥量 */
    			pthread_mutex_unlock(&g_tMutex);
    		}
    	}
    
    	return NULL;
    }
    
    int AllInputDevicesInit(void)
    {
    	PT_InputOpr ptTmp = g_ptInputOprHead;
    	int iError = -1;
    
    	while (ptTmp)
    	{
    		if (0 == ptTmp->DeviceInit())
    		{
    			/* 创建子线程 */
    			pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent);			
    			iError = 0;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return iError;
    }
    
    int GetInputEvent(PT_InputEvent ptInputEvent)
    {
    	/* 休眠 */
    	pthread_mutex_lock(&g_tMutex);
    	pthread_cond_wait(&g_tConVar, &g_tMutex);	
    
    	/* 被唤醒后,返回数据 */
    	*ptInputEvent = g_tInputEvent;
    	pthread_mutex_unlock(&g_tMutex);
    	return 0;	
    }
    
    int InputInit(void)
    {
    	int iError;
    	iError = StdinInit();
    	iError |= TouchScreenInit();
    	return iError;
    }
    

    stdin.c

    /*    使用轮询的方式去访问    */
    #include <input_manager.h>
    #include <termios.h>
    #include <unistd.h>
    #include <stdio.h>
    
    
    static int StdinDevInit(void)
    {
    	struct termios tTTYState;
    
    	//get the terminal state
    	tcgetattr(STDIN_FILENO, &tTTYState);
    
    	//turn off canonical mode
    	tTTYState.c_lflag &= ~ICANON;
    	//minimum of number input read.
    	tTTYState.c_cc[VMIN] = 1;   /* 有一个数据时就立刻返回 */
    
    	//set the terminal attributes.
    	tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);
    
    	return 0;
    }
    
    static int StdinDevExit(void)
    {
    
    	struct termios tTTYState;
    
    	//get the terminal state
    	tcgetattr(STDIN_FILENO, &tTTYState);
    
    	//turn on canonical mode
    	tTTYState.c_lflag |= ICANON;
    	
    	//set the terminal attributes.
    	tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);	
    	return 0;
    }
    
    static int StdinGetInputEvent(PT_InputEvent ptInputEvent)
    {
    	/* 如果有数据就读取、处理、返回
    	* 如果没有数据, 立刻返回, 不等待
    	*/
    
    	/* select, poll 可以参数 UNIX环境高级编程 */
    
    	char c;
    	
    		/* 处理数据 */
    	ptInputEvent->iType = INPUT_TYPE_STDIN;
    	
    	c = fgetc(stdin);  /* 会休眠直到有输入 */
    	gettimeofday(&ptInputEvent->tTime, NULL);
    	
    	if (c == 'u')
    	{
    		ptInputEvent->iVal = INPUT_VALUE_UP;
    	}
    	else if (c == 'n')
    	{
    		ptInputEvent->iVal = INPUT_VALUE_DOWN;
    	}
    	else if (c == 'q')
    	{
    		ptInputEvent->iVal = INPUT_VALUE_EXIT;
    	}
    	else
    	{
    		ptInputEvent->iVal = INPUT_VALUE_UNKNOWN;
    	}		
    	return 0;
    }
    
    static T_InputOpr g_tStdinOpr = {
    	.name          = "stdin",
    	.DeviceInit    = StdinDevInit,
    	.DeviceExit    = StdinDevExit,
    	.GetInputEvent = StdinGetInputEvent,
    };
    
    
    int StdinInit(void)
    {
    	return RegisterInputOpr(&g_tStdinOpr);
    }
    

    touchscreen.c

    #include <config.h>
    #include <input_manager.h>
    #include <stdlib.h>
    
    #include <tslib.h>
    #include <draw.h>
    
    /* 参考tslib里的ts_print.c */
    
    static struct tsdev *g_tTSDev;
    static int giXres;
    static int giYres;
    
    /* 注意: 由于要用到LCD的分辨率, 此函数要在SelectAndInitDisplay之后调用 */
    static int TouchScreenDevInit(void)
    {
    	char *pcTSName = NULL;
    
        /*    getenv从环境中取字符串,获取环境变量的值    
         *    指定触摸屏设备 TSLIB_TSDEVICE=/dev/input/touchscreen0
         */
    	if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL ) 
    	{
    		g_tTSDev = ts_open(pcTSName, 0);  /* 以阻塞方式打开 */
    	}
    	else
    	{
    		g_tTSDev = ts_open("/dev/event0", 1);
    	}
    
    	if (!g_tTSDev) {
    		DBG_PRINTF(APP_ERR"ts_open error!
    ");
    		return -1;
    	}
    
        /*    配置    */
    	if (ts_config(g_tTSDev)) {
    		DBG_PRINTF("ts_config error!
    ");
    		return -1;
    	}
    
    	if (GetDispResolution(&giXres, &giYres))
    	{
    		return -1;
    	}
    
    	return 0;
    }
    
    static int TouchScreenDevExit(void)
    {
    	return 0;
    }
    
    
    static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
    {
    	int iPreMs;
    	int iNowMs;
    	
    	iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
    	iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;
    
    	return (iNowMs > iPreMs + 500);
    }
    
    static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent)
    {
    	struct ts_sample tSamp;
    	struct ts_sample tSampPressed;
    	struct ts_sample tSampReleased;
    	int iRet;
    	int bStart = 0;
    	int iDelta;
    
    	static struct timeval tPreTime;
    	
    
    	while (1)
    	{
    		iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 */
    		if (iRet == 1)
    		{
    			if ((tSamp.pressure > 0) && (bStart == 0))
    			{
    				/* 刚按下 */
    				/* 记录刚开始压下的点 */
    				tSampPressed = tSamp;
    				bStart = 1;
    			}
    			
    			if (tSamp.pressure <= 0)
    			{
    				/* 松开 */
    				tSampReleased = tSamp;
    
    				/* 处理数据 */
    				if (!bStart)
    				{
    					return -1;
    				}
    				else
    				{
    					iDelta = tSampReleased.x - tSampPressed.x;
    					ptInputEvent->tTime = tSampReleased.tv;
    					ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;
    					
    					if (iDelta > giXres/5)
    					{
    						/* 翻到上一页 */
    						ptInputEvent->iVal = INPUT_VALUE_UP;
    					}
    					else if (iDelta < 0 - giXres/5)
    					{
    						/* 翻到下一页 */
    						ptInputEvent->iVal = INPUT_VALUE_DOWN;
    					}
    					else
    					{
    						ptInputEvent->iVal = INPUT_VALUE_UNKNOWN;
    					}
    					return 0;
    				}
    			}
    		}
    		else
    		{
    			return -1;
    		}
    	}
    
    	return 0;
    }
    
    
    static T_InputOpr g_tTouchScreenOpr = {
    	.name          = "touchscreen",
    	.DeviceInit    = TouchScreenDevInit,
    	.DeviceExit    = TouchScreenDevExit,
    	.GetInputEvent = TouchScreenGetInputEvent,
    };
    
    int TouchScreenInit(void)
    {
    	return RegisterInputOpr(&g_tTouchScreenOpr);
    }
    

    debug模块(debug目录)

    Makefile

    	obj-y += debug_manager.o
    obj-y += stdout.o
    obj-y += netprint.o
    

    debug_manager.h

    #ifndef _DEBUG_MANAGER_H
    #define _DEBUG_MANAGER_H
    
    #define	APP_EMERG	"<0>"	/* system is unusable			*/
    #define	APP_ALERT	"<1>"	/* action must be taken immediately	*/
    #define	APP_CRIT	"<2>"	/* critical conditions			*/
    #define	APP_ERR	    "<3>"	/* error conditions			*/
    #define	APP_WARNING	"<4>"	/* warning conditions			*/
    #define	APP_NOTICE	"<5>"	/* normal but significant condition	*/
    #define	APP_INFO	"<6>"	/* informational			*/
    #define	APP_DEBUG	"<7>"	/* debug-level messages			*/
    
    #define DEFAULT_DBGLEVEL  4
    
    typedef struct DebugOpr {
    	char *name;
    	int isCanUse;
    	int (*DebugInit)(void);
    	int (*DebugExit)(void);
    	int (*DebugPrint)(char *strData);
    	struct DebugOpr *ptNext;
    }T_DebugOpr, *PT_DebugOpr;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
    void ShowDebugOpr(void);
    PT_DebugOpr GetDebugOpr(char *pcName);
    int SetDbgLevel(char *strBuf);
    int SetDbgChanel(char *strBuf);
    int DebugInit(void);
    int DebugPrint(const char *pcFormat, ...);
    int InitDebugChanel(void);
    
    #endif /* _DEBUG_MANAGER_H */
    
    #ifndef _DEBUG_MANAGER_H
    #define _DEBUG_MANAGER_H
    
    /*    打印优先级设置    */
    #define	APP_EMERG	"<0>"	/* system is unusable			*/
    #define	APP_ALERT	"<1>"	/* action must be taken immediately	*/
    #define	APP_CRIT	"<2>"	/* critical conditions			*/
    #define	APP_ERR	    "<3>"	/* error conditions			*/
    #define	APP_WARNING	"<4>"	/* warning conditions			*/
    #define	APP_NOTICE	"<5>"	/* normal but significant condition	*/
    #define	APP_INFO	"<6>"	/* informational			*/
    #define	APP_DEBUG	"<7>"	/* debug-level messages			*/
    
    #define DEFAULT_DBGLEVEL  4
    
    typedef struct DebugOpr {
    	char *name;
    	int isCanUse;
    	int (*DebugInit)(void);
    	int (*DebugExit)(void);
    	int (*DebugPrint)(char *strData);
    	struct DebugOpr *ptNext;
    }T_DebugOpr, *PT_DebugOpr;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
    void ShowDebugOpr(void);
    PT_DebugOpr GetDebugOpr(char *pcName);
    int SetDbgLevel(char *strBuf);
    int SetDbgChanel(char *strBuf);
    int DebugInit(void);
    int DebugPrint(const char *pcFormat, ...);
    int InitDebugChanel(void);
    
    #endif /* _DEBUG_MANAGER_H */
    

    debug_manager.c

    #include <config.h>
    #include <debug_manager.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdarg.h>
    
    static PT_DebugOpr g_ptDebugOprHead;
    static int g_iDbgLevelLimit = 8;
    
    int RegisterDebugOpr(PT_DebugOpr ptDebugOpr)
    {
    	PT_DebugOpr ptTmp;
    
    	if (!g_ptDebugOprHead)
    	{
    		g_ptDebugOprHead   = ptDebugOpr;
    		ptDebugOpr->ptNext = NULL;
    	}
    	else
    	{
    		ptTmp = g_ptDebugOprHead;
    		while (ptTmp->ptNext)
    		{
    			ptTmp = ptTmp->ptNext;
    		}
    		ptTmp->ptNext	  = ptDebugOpr;
    		ptDebugOpr->ptNext = NULL;
    	}
    
    	return 0;
    }
    
    
    void ShowDebugOpr(void)
    {
    	int i = 0;
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    
    	while (ptTmp)
    	{
    		printf("%02d %s
    ", i++, ptTmp->name);
    		ptTmp = ptTmp->ptNext;
    	}
    }
    
    PT_DebugOpr GetDebugOpr(char *pcName)
    {
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	
    	while (ptTmp)
    	{
    		if (strcmp(ptTmp->name, pcName) == 0)
    		{
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    	return NULL;
    }
    
    
    /* strBuf = "dbglevel=6" */
    int SetDbgLevel(char *strBuf)
    {
    	g_iDbgLevelLimit = strBuf[9] - '0';
    	return 0;
    }
    
    /*
    * stdout=0			   : 关闭stdout打印
    * stdout=1			   : 打开stdout打印
    * netprint=0		   : 关闭netprint打印
    * netprint=1		   : 打开netprint打印
    */
    
    int SetDbgChanel(char *strBuf)
    {
    	char *pStrTmp;
    	char strName[100];
    	PT_DebugOpr ptTmp;
        /*    strchr函数功能为在一个串中查找给定字符的第一个匹配之处    */
    	pStrTmp = strchr(strBuf, '=');
    	if (!pStrTmp)
    	{
    		return -1;
    	}
    	else
    	{
    		strncpy(strName, strBuf, pStrTmp-strBuf);
    		strName[pStrTmp-strBuf] = '';
    		ptTmp = GetDebugOpr(strName);
    		if (!ptTmp)
    			return -1;
    
    		if (pStrTmp[1] == '0')
    			ptTmp->isCanUse = 0;
    		else
    			ptTmp->isCanUse = 1;
    		return 0;
    	}
    	
    }
    
    
    int DebugPrint(const char *pcFormat, ...)
    {
    	char strTmpBuf[1000];
    	char *pcTmp;
    	va_list tArg;
    	int iNum;
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	int dbglevel = DEFAULT_DBGLEVEL;
    	
        /*    va_start函数来获取参数列表中的参数    */
    	va_start (tArg, pcFormat);
    
        /*     int vsprintf(char *string, char *format, va_list param);//将param 按格式format写入字符串string中    */
    	iNum = vsprintf (strTmpBuf, pcFormat, tArg);
    	va_end (tArg);
    	strTmpBuf[iNum] = '';
    
    
    	pcTmp = strTmpBuf;
    	
    	/* 根据打印级别决定是否打印 */
    	if ((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>'))
    	{
    		dbglevel = strTmpBuf[1] - '0';
    		if (dbglevel >= 0 && dbglevel <= 9)
    		{
    			pcTmp = strTmpBuf + 3;
    		}
    		else
    		{
    			dbglevel = DEFAULT_DBGLEVEL;
    		}
    	}
    
    	if (dbglevel > g_iDbgLevelLimit)
    	{
    		return -1;
    	}
    
    	/* 调用链表中所有isCanUse为1的结构体的DebugPrint函数 */
    	while (ptTmp)
    	{
    		if (ptTmp->isCanUse)
    		{
    			ptTmp->DebugPrint(pcTmp);
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	return 0;
    	
    }
    
    int DebugInit(void)
    {
    	int iError;
    
    	iError = StdoutInit();
    	iError |= NetPrintInit();
    	return iError;
    }
    
    int InitDebugChanel(void)
    {
    	PT_DebugOpr ptTmp = g_ptDebugOprHead;
    	while (ptTmp)
    	{
    		if (ptTmp->isCanUse && ptTmp->DebugInit)
    		{
    			ptTmp->DebugInit();
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	return 0;}
    

    stdout.c

    #include <config.h>
    #include <debug_manager.h>
    #include <stdio.h>
    #include <string.h>
    
    
    static int StdoutDebugPrint(char *strData)
    {
    	/* 直接把输出信息用printf打印出来 */
    	printf("%s", strData);
    	return strlen(strData);	
    }
    
    static T_DebugOpr g_tStdoutDbgOpr = {
    	.name       = "stdout",
    	.isCanUse   = 1,
    	.DebugPrint = StdoutDebugPrint,
    };
    
    int StdoutInit(void)
    {
    	return RegisterDebugOpr(&g_tStdoutDbgOpr);
    }
    

    netprint.c(不难看出采用的是UDP协议)

    #include <config.h>
    #include <debug_manager.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #define SERVER_PORT 5678
    /*    分配16k的buf    */
    #define PRINT_BUF_SIZE   (16*1024)
    
    static int g_iSocketServer;
    static struct sockaddr_in g_tSocketServerAddr;
    static struct sockaddr_in g_tSocketClientAddr;
    static int g_iHaveConnected = 0;
    static char *g_pcNetPrintBuf;
    static int g_iReadPos  = 0;
    static int g_iWritePos = 0;
    
    static pthread_t g_tSendTreadID;
    static pthread_t g_tRecvTreadID;
    
    static pthread_mutex_t g_tNetDbgSendMutex  = PTHREAD_MUTEX_INITIALIZER;
    static pthread_cond_t  g_tNetDbgSendConVar = PTHREAD_COND_INITIALIZER;
    
    /*    环形缓冲区    */
    static int isFull(void)
    {
    	return (((g_iWritePos + 1) % PRINT_BUF_SIZE) == g_iReadPos);
    }
    
    static int isEmpty(void)
    {
    	return (g_iWritePos == g_iReadPos);
    }
    
    
    static int PutData(char cVal)
    {
    	if (isFull())
    		return -1;
    	else
    	{
    		g_pcNetPrintBuf[g_iWritePos] = cVal;
    		g_iWritePos = (g_iWritePos + 1) % PRINT_BUF_SIZE;
    		return 0;
    	}	
    }
    
    static int GetData(char *pcVal)
    {
    	if (isEmpty())
    		return -1;
    	else
    	{
    		*pcVal = g_pcNetPrintBuf[g_iReadPos];
    		g_iReadPos = (g_iReadPos + 1) % PRINT_BUF_SIZE;
    		return 0;
    	}
    }
    
    
    static void *NetDbgSendTreadFunction(void *pVoid)
    {
    	char strTmpBuf[512];
    	char cVal;
    	int i;
    	int iAddrLen;
    	int iSendLen;
    	
    	while (1)
    	{
    		/* 平时休眠 */
    		pthread_mutex_lock(&g_tNetDbgSendMutex);
    		pthread_cond_wait(&g_tNetDbgSendConVar, &g_tNetDbgSendMutex);	
    		pthread_mutex_unlock(&g_tNetDbgSendMutex);
    
    		while (g_iHaveConnected && !isEmpty())
    		{
    			i = 0;
    
    			/* 把环形缓冲区的数据取出来, 最多取512字节 */
    			while ((i < 512) && (0 == GetData(&cVal)))
    			{
    				strTmpBuf[i] = cVal;
    				i++;
    			}
    			
    			/* 执行到这里, 表示被唤醒 */
    			/* 用sendto函数发送打印信息给客户端 */
    			iAddrLen = sizeof(struct sockaddr);
    			iSendLen = sendto(g_iSocketServer, strTmpBuf, i, 0,
    								(const struct sockaddr *)&g_tSocketClientAddr, iAddrLen);
    
    		}
    
    	}
    	return NULL;
    }
    
    static void *NetDbgRecvTreadFunction(void *pVoid)
    {
    	socklen_t iAddrLen;
    	int iRecvLen;
    	char ucRecvBuf[1000];
    	struct sockaddr_in tSocketClientAddr;
    
    	while (1)
    	{
    		iAddrLen = sizeof(struct sockaddr);
    		DBG_PRINTF("in NetDbgRecvTreadFunction
    ");
    		iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    		
    		if (iRecvLen > 0)	
    		{
    			ucRecvBuf[iRecvLen] = '';
    			DBG_PRINTF("netprint.c get msg: %s
    ", ucRecvBuf);
    			
    			/* 解析数据:
    			* setclient            : 设置接收打印信息的客户端
    			* dbglevel=0,1,2...    : 修改打印级别
    			* stdout=0             : 关闭stdout打印
    			* stdout=1             : 打开stdout打印
    			* netprint=0           : 关闭netprint打印
    			* netprint=1           : 打开netprint打印
    			*/
    			if (strcmp(ucRecvBuf, "setclient")  == 0)
    			{
    				g_tSocketClientAddr = tSocketClientAddr;
    				g_iHaveConnected = 1;
    			}
    			else if (strncmp(ucRecvBuf, "dbglevel=", 9) == 0)
    			{
    				SetDbgLevel(ucRecvBuf);
    			}
    			else
    			{
    				SetDbgChanel(ucRecvBuf);
    			}
    		}
    		
    	}
    	return NULL;
    }
    
    
    static int NetDbgInit(void)
    {
    	/* socket初始化 */
    	int iRet;
    	
    	g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
    	if (-1 == g_iSocketServer)
    	{
    		printf("socket error!
    ");
    		return -1;
    	}
    
    	g_tSocketServerAddr.sin_family      = AF_INET;
    	g_tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    	g_tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    	memset(g_tSocketServerAddr.sin_zero, 0, 8);
    	
    	iRet = bind(g_iSocketServer, (const struct sockaddr *)&g_tSocketServerAddr, sizeof(struct sockaddr));
    	if (-1 == iRet)
    	{
    		printf("bind error!
    ");
    		return -1;
    	}
    
    	g_pcNetPrintBuf = malloc(PRINT_BUF_SIZE);
    	if (NULL == g_pcNetPrintBuf)
    	{
    		close(g_iSocketServer);
    		return -1;
    	}
    
    
    	/* 创建netprint发送线程: 它用来发送打印信息给客户端 */
    	pthread_create(&g_tSendTreadID, NULL, NetDbgSendTreadFunction, NULL);			
    	
    	/* 创建netprint接收线否: 用来接收控制信息,比如修改打印级别,打开/关闭打印 */
    	pthread_create(&g_tRecvTreadID, NULL, NetDbgRecvTreadFunction, NULL);			
    
    	return 0;	
    }
    
    static int NetDbgExit(void)
    {
    	/* 关闭socket,... */
    	close(g_iSocketServer);
    	free(g_pcNetPrintBuf);
    }
    
    static int NetDbgPrint(char *strData)
    {
    	/* 把数据放入环形缓冲区 */
    	int i;
    	
    	for (i = 0; i < strlen(strData); i++)
    	{
    		if (0 != PutData(strData[i]))
    			break;
    	}
    	
    	/* 如果已经有客户端连接了, 就把数据通过网络发送给客户端 */
    	/* 唤醒netprint的发送线程 */
    	pthread_mutex_lock(&g_tNetDbgSendMutex);
    	pthread_cond_signal(&g_tNetDbgSendConVar);
    	pthread_mutex_unlock(&g_tNetDbgSendMutex);
    
    	return i;
    	
    }
    
    
    static T_DebugOpr g_tNetDbgOpr = {
    	.name       = "netprint",
    	.isCanUse   = 1,
    	.DebugInit  = NetDbgInit,
    	.DebugExit  = NetDbgExit,
    	.DebugPrint = NetDbgPrint,
    };
    
    int NetPrintInit(void)
    {
    	return RegisterDebugOpr(&g_tNetDbgOpr);
    }
    

    netprintclien.c(工程目录下)

    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    
    /* socket
    * connect
    * send/recv
    */
    
    #define SERVER_PORT 5678
    
    
    /*
    * ./netprint_client <server_ip> dbglevel=<0-9>
    * ./netprint_client <server_ip> stdout=0|1
    * ./netprint_client <server_ip> netprint=0|1
    * ./netprint_client <server_ip> show // setclient,并且接收打印信息
    */
    
    int main(int argc, char **argv)
    {
    	int iSocketClient;
    	struct sockaddr_in tSocketServerAddr;
    	
    	int iRet;
    	unsigned char ucRecvBuf[1000];
    	int iSendLen;
    	int iRecvLen;
    	int iAddrLen;
    
    	if (argc != 3)
    	{
    		printf("Usage:
    ");
    		printf("%s <server_ip> dbglevel=<0-9>
    ", argv[0]);
    		printf("%s <server_ip> stdout=0|1
    ", argv[0]);
    		printf("%s <server_ip> netprint=0|1
    ", argv[0]);
    		printf("%s <server_ip> show
    ", argv[0]);
    		return -1;
    	}
    
    	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
    
    	tSocketServerAddr.sin_family      = AF_INET;
    	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
    	{
    		printf("invalid server_ip
    ");
    		return -1;
    	}
    	memset(tSocketServerAddr.sin_zero, 0, 8);
    
    	if (strcmp(argv[2], "show") == 0)
    	{
    		/* 发送数据 */
    		iAddrLen = sizeof(struct sockaddr);
    		iSendLen = sendto(iSocketClient, "setclient", 9, 0,
    							(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
    
    		while (1)
    		{
    			/* 循环: 从网络读数据, 打印出来 */
    			iAddrLen = sizeof(struct sockaddr);
    			iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketServerAddr, &iAddrLen);
    			if (iRecvLen > 0)
    			{
    				ucRecvBuf[iRecvLen] = '';
    				printf("%s
    ", ucRecvBuf);
    			}
    		}
    	}
    	else
    	{
    		/* 发送数据 */
    		iAddrLen = sizeof(struct sockaddr);
    		iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,
    							(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
    	}
    
    	return 0;
    }
    

    draw模块(draw目录)

    Makefile

    obj-y += draw.o
    

    draw.c

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <config.h>
    #include <draw.h>
    #include <encoding_manager.h>
    #include <fonts_manager.h>
    #include <disp_manager.h>
    #include <string.h>
    
    
    typedef struct PageDesc {
    	int iPage;
    	unsigned char *pucLcdFirstPosAtFile;
    	unsigned char *pucLcdNextPageFirstPosAtFile;
    	struct PageDesc *ptPrePage;
    	struct PageDesc *ptNextPage;
    } T_PageDesc, *PT_PageDesc;
    
    static int g_iFdTextFile;
    static unsigned char *g_pucTextFileMem;
    static unsigned char *g_pucTextFileMemEnd;
    static PT_EncodingOpr g_ptEncodingOprForFile;
    
    static PT_DispOpr g_ptDispOpr;
    
    /*    在lcd上第一个字符在文件中的位置    */
    static unsigned char *g_pucLcdFirstPosAtFile;
    /*    lcd上下一页的第一个字符在文件中的位置    */
    static unsigned char *g_pucLcdNextPosAtFile;
    
    static int g_dwFontSize;
    
    static PT_PageDesc g_ptPages   = NULL;
    static PT_PageDesc g_ptCurPage = NULL;
    
    
    int OpenTextFile(char *pcFileName)
    {
    	struct stat tStat;
    
    	g_iFdTextFile = open(pcFileName, O_RDONLY);
    	if (0 > g_iFdTextFile)
    	{
    		DBG_PRINTF("can't open text file %s
    ", pcFileName);
    		return -1;
    	}
    
    	if(fstat(g_iFdTextFile, &tStat))
    	{
    		DBG_PRINTF("can't get fstat
    ");
    		return -1;
    	}
    	g_pucTextFileMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdTextFile, 0);
    	if (g_pucTextFileMem == (unsigned char *)-1)
    	{
    		DBG_PRINTF("can't mmap for text file
    ");
    		return -1;
    	}
    
    	g_pucTextFileMemEnd = g_pucTextFileMem + tStat.st_size;
    	
    	g_ptEncodingOprForFile = SelectEncodingOprForFile(g_pucTextFileMem);
    
    	if (g_ptEncodingOprForFile)
    	{
    
            /*    注意:这里加上了文件前面的特殊编码空间    */
    		g_pucLcdFirstPosAtFile = g_pucTextFileMem + g_ptEncodingOprForFile->iHeadLen;
    		return 0;
    	}
    	else
    	{
    		return -1;
    	}
    
    }
    
    /*    根据得到的编码中的字形结构体来确定,字形    */
    int SetTextDetail(char *pcHZKFile, char *pcFileFreetype, unsigned int dwFontSize)
    {
    	int iError = 0;
    	PT_FontOpr ptFontOpr;
    	PT_FontOpr ptTmp;
    	int iRet = -1;
    
    	g_dwFontSize = dwFontSize;
    	
    
    	ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
    	while (ptFontOpr)
    	{
            /*    根据名字选择,传入的字体文件,设置大小    */
    		if (strcmp(ptFontOpr->name, "ascii") == 0)
    		{
    			iError = ptFontOpr->FontInit(NULL, dwFontSize);
    		}
    		else if (strcmp(ptFontOpr->name, "gbk") == 0)
    		{
    			iError = ptFontOpr->FontInit(pcHZKFile, dwFontSize);
    		}
    		else
    		{
    			iError = ptFontOpr->FontInit(pcFileFreetype, dwFontSize);
    		}
    
    		DBG_PRINTF("%s, %d
    ", ptFontOpr->name, iError);
    
    		ptTmp = ptFontOpr->ptNext;
    
    		if (iError == 0)
    		{
    			/* 比如对于ascii编码的文件, 可能用ascii字体也可能用gbk字体, 
    			* 所以只要有一个FontInit成功, SetTextDetail最终就返回成功
    			*/
    			iRet = 0;
    		}
    		else
    		{
    			DelFontOprFrmEncoding(g_ptEncodingOprForFile, ptFontOpr);
    		}
    		ptFontOpr = ptTmp;
    	}
    	return iRet;
    }
    
    int SelectAndInitDisplay(char *pcName)
    {
    	int iError;
    	g_ptDispOpr = GetDispOpr(pcName);
    	if (!g_ptDispOpr)
    	{
    		return -1;
    	}
    
    	iError = g_ptDispOpr->DeviceInit();
    	return iError;
    }
    
    int GetDispResolution(int *piXres, int *piYres)
    {
    	if (g_ptDispOpr)
    	{
    		*piXres = g_ptDispOpr->iXres;
    		*piYres = g_ptDispOpr->iYres;
    		return 0;
    	}
    	else
    	{
    		return -1;
    	}
    }
    
    int IncLcdX(int iX)
    {
    	if (iX + 1 < g_ptDispOpr->iXres)
    		return (iX + 1);
    	else
    		return 0;
    }
    
    /*    换行    */
    int IncLcdY(int iY)
    {
    	if (iY + g_dwFontSize < g_ptDispOpr->iYres)
    		return (iY + g_dwFontSize);
    	else
    		return 0;
    }
    
    int RelocateFontPos(PT_FontBitMap ptFontBitMap)
    {
    	int iLcdY;
    	int iDeltaX;
    	int iDeltaY;
    
    	if (ptFontBitMap->iYMax > g_ptDispOpr->iYres)
    	{
    		/* 满页了 */
    		return -1;
    	}
    
    	/* 超过LCD最右边 */
    	if (ptFontBitMap->iXMax > g_ptDispOpr->iXres)
    	{
    		/* 换行 */		
    		iLcdY = IncLcdY(ptFontBitMap->iCurOriginY);
    		if (0 == iLcdY)
    		{
    			/* 满页了 */
    			return -1;
    		}
    		else
    		{
    			/* 没满页,重新计算位置 */
    			iDeltaX = 0 - ptFontBitMap->iCurOriginX;
    			iDeltaY = iLcdY - ptFontBitMap->iCurOriginY;
    
    			ptFontBitMap->iCurOriginX  += iDeltaX;
    			ptFontBitMap->iCurOriginY  += iDeltaY;
    
    			ptFontBitMap->iNextOriginX += iDeltaX;
    			ptFontBitMap->iNextOriginY += iDeltaY;
    
    			ptFontBitMap->iXLeft += iDeltaX;
    			ptFontBitMap->iXMax  += iDeltaX;
    
    			ptFontBitMap->iYTop  += iDeltaY;
    			ptFontBitMap->iYMax  += iDeltaY;;
    			
    			return 0;	
    		}
    	}
    	
    	return 0;
    }
    
    int ShowOneFont(PT_FontBitMap ptFontBitMap)
    {
    	int x;
    	int y;
    	unsigned char ucByte = 0;
    	int i = 0;
    	int bit;
    	
    	if (ptFontBitMap->iBpp == 1)
    	{
    		for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
    		{
    			i = (y - ptFontBitMap->iYTop) * ptFontBitMap->iPitch;
    			for (x = ptFontBitMap->iXLeft, bit = 7; x < ptFontBitMap->iXMax; x++)
    			{
    				if (bit == 7)
    				{
    					ucByte = ptFontBitMap->pucBuffer[i++];
    				}
    				
    				if (ucByte & (1<<bit))
    				{
    					g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
    				}
    				else
    				{
    					/* 使用背景色, 不用描画 */
    					// g_ptDispOpr->ShowPixel(x, y, 0); /* 黑 */
    				}
    				bit--;
    				if (bit == -1)
    				{
    					bit = 7;
    				}
    			}
    		}
    	}
    	else if (ptFontBitMap->iBpp == 8)
    	{
    		for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
    			for (x = ptFontBitMap->iXLeft; x < ptFontBitMap->iXMax; x++)
    			{
    				//g_ptDispOpr->ShowPixel(x, y, ptFontBitMap->pucBuffer[i++]);
    				if (ptFontBitMap->pucBuffer[i++])
    					g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
    			}
    	}
    	else
    	{
    		DBG_PRINTF("ShowOneFont error, can't support %d bpp
    ", ptFontBitMap->iBpp);
    		return -1;
    	}
    	return 0;
    }
    
    int ShowOnePage(unsigned char *pucTextFileMemCurPos)
    {
    	int iLen;
    	int iError;
    	unsigned char *pucBufStart;
    	unsigned int dwCode;
    	PT_FontOpr ptFontOpr;
    	T_FontBitMap tFontBitMap;
    	
    	int bHasNotClrSceen = 1;
    	int bHasGetCode = 0;
    
    	tFontBitMap.iCurOriginX = 0;
    	tFontBitMap.iCurOriginY = g_dwFontSize;
    	pucBufStart = pucTextFileMemCurPos;
    
    	
    	while (1)
    	{
    		iLen = g_ptEncodingOprForFile->GetCodeFrmBuf(pucBufStart, g_pucTextFileMemEnd, &dwCode);
    		if (0 == iLen)
    		{
    			/* 文件结束 */
    			if (!bHasGetCode)
    			{
    				return -1;
    			}
    			else
    			{
    				return 0;
    			}
    		}
    
    		bHasGetCode = 1;
    		
    		pucBufStart += iLen;
    
    		/* 有些文本, 
    
    两个一起才表示回车换行
    		* 碰到这种连续的
    
    , 只处理一次
    		*/
    		if (dwCode == '
    ')
    		{
    			g_pucLcdNextPosAtFile = pucBufStart;
    			
    			/* 回车换行 */
    			tFontBitMap.iCurOriginX = 0;
    			tFontBitMap.iCurOriginY = IncLcdY(tFontBitMap.iCurOriginY);
    			if (0 == tFontBitMap.iCurOriginY)
    			{
    				/* 显示完当前一屏了 */
    				return 0;
    			}
    			else
    			{
    				continue;
    			}
    		}
    		else if (dwCode == '
    ')
    		{
    			continue;
    		}
    		else if (dwCode == '	')
    		{
    			/* TAB键用一个空格代替 */
    			dwCode = ' ';
    		}
    
    		DBG_PRINTF("dwCode = 0x%x
    ", dwCode);
    		
    		ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
    		while (ptFontOpr)
    		{
    			DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    			iError = ptFontOpr->GetFontBitmap(dwCode, &tFontBitMap);
    			DBG_PRINTF("%s %s %d, ptFontOpr->name = %s, %d
    ", __FILE__, __FUNCTION__, __LINE__, ptFontOpr->name, iError);
    			if (0 == iError)
    			{
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    				if (RelocateFontPos(&tFontBitMap))
    				{
    					/* 剩下的LCD空间不能满足显示这个字符 */
    					return 0;
    				}
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    				if (bHasNotClrSceen)
    				{
    					/* 首先清屏 */
    					g_ptDispOpr->CleanScreen(COLOR_BACKGROUND);
    					bHasNotClrSceen = 0;
    				}
    				DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    				/* 显示一个字符 */
    				if (ShowOneFont(&tFontBitMap))
    				{
    					return -1;
    				}
    				
    				tFontBitMap.iCurOriginX = tFontBitMap.iNextOriginX;
    				tFontBitMap.iCurOriginY = tFontBitMap.iNextOriginY;
    				g_pucLcdNextPosAtFile = pucBufStart;
    
    				/* 继续取出下一个编码来显示 */
    				break;
    			}
    			ptFontOpr = ptFontOpr->ptNext;
    		}		
    	}
    
    	return 0;
    }
    
    /*    记录下当前这一页的数据,保存到链表    */
    static void RecordPage(PT_PageDesc ptPageNew)
    {
    	PT_PageDesc ptPage;
    		
    	if (!g_ptPages)
    	{
    		g_ptPages = ptPageNew;
    	}
    	else
    	{
    		ptPage = g_ptPages;
    		while (ptPage->ptNextPage)
    		{
    			ptPage = ptPage->ptNextPage;
    		}
    		ptPage->ptNextPage   = ptPageNew;
    		ptPageNew->ptPrePage = ptPage;
    	}
    }
    
    int ShowNextPage(void)
    {
    	int iError;
    	PT_PageDesc ptPage;
    	unsigned char *pucTextFileMemCurPos;
    
        /*    如果当前页面不为空,则保存当前页面
         *    否则,则证明,这是第一页。则把第一页的数据放进了
         */
    	if (g_ptCurPage)
    	{
    		pucTextFileMemCurPos = g_ptCurPage->pucLcdNextPageFirstPosAtFile;
    	}
    	else
    	{
    		pucTextFileMemCurPos = g_pucLcdFirstPosAtFile;
    	}
    	iError = ShowOnePage(pucTextFileMemCurPos);
    	DBG_PRINTF("%s %d, %d
    ", __FUNCTION__, __LINE__, iError);
    	if (iError == 0)
    	{
            /*    iError == 0表示显示完当前页,此时把链表指向下一页    */
    		if (g_ptCurPage && g_ptCurPage->ptNextPage)
    		{
    			g_ptCurPage = g_ptCurPage->ptNextPage;
    			return 0;
    		}
    		
    		ptPage = malloc(sizeof(T_PageDesc));
    		if (ptPage)
    		{
    			ptPage->pucLcdFirstPosAtFile         = pucTextFileMemCurPos;
    			ptPage->pucLcdNextPageFirstPosAtFile = g_pucLcdNextPosAtFile;
    			ptPage->ptPrePage                    = NULL;
    			ptPage->ptNextPage                   = NULL;
    			g_ptCurPage = ptPage;
    			DBG_PRINTF("%s %d, pos = 0x%x
    ", __FUNCTION__, __LINE__, (unsigned int)ptPage->pucLcdFirstPosAtFile);
    			RecordPage(ptPage);
    			return 0;
    		}
    		else
    		{
    			return -1;
    		}
    	}
    	return iError;
    }
    
    int ShowPrePage(void)
    {
    	int iError;
    
    	DBG_PRINTF("%s %d
    ", __FUNCTION__, __LINE__);
    	if (!g_ptCurPage || !g_ptCurPage->ptPrePage)
    	{
    		return -1;
    	}
    
    	DBG_PRINTF("%s %d, pos = 0x%x
    ", __FUNCTION__, __LINE__, (unsigned int)g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
    	iError = ShowOnePage(g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
    	if (iError == 0)
    	{
    		DBG_PRINTF("%s %d
    ", __FUNCTION__, __LINE__);
    		g_ptCurPage = g_ptCurPage->ptPrePage;
    	}
    	return iError;
    }
    

    main.c

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <config.h>
    #include <draw.h>
    #include <encoding_manager.h>
    #include <fonts_manager.h>
    #include <disp_manager.h>
    #include <input_manager.h>
    #include <string.h>
    
    
    /* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */
    int main(int argc, char **argv)
    {
    	int iError;
    	unsigned int dwFontSize = 16;
    	char acHzkFile[128];
    	char acFreetypeFile[128];
    	char acTextFile[128];
    
    	char acDisplay[128];
    
    	int bList = 0;
    
    	T_InputEvent tInputEvent;
    
    	acHzkFile[0]  = '';
    	acFreetypeFile[0] = '';
    	acTextFile[0] = '';
    
    	strcpy(acDisplay, "fb");
    
    	iError = DebugInit();
    	if (iError)
    	{
    		DBG_PRINTF("DebugInit error!
    ");
    		return -1;
    	}
    
    	InitDebugChanel();
    	
        /*    getopt得到输入的命令    */
    	while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)
    	{
    		switch(iError)
    		{
    			case 'l':
    			{
    				bList = 1;
    				break;
    			}
    			case 's':
    			{
    				dwFontSize = strtoul(optarg, NULL, 0);
    				break;
    			}
    			case 'f':
    			{
    				strncpy(acFreetypeFile, optarg, 128);
    				acFreetypeFile[127] = '';
    				break;
    			}			
    			case 'h':
    			{
    					strncpy(acHzkFile, optarg, 128);
    					acHzkFile[127] = '';
    					break;
    			}
    			case 'd':
    			{
    				strncpy(acDisplay, optarg, 128);
    				acDisplay[127] = '';
    				break;
    			}
    			default:
    			{
    					DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>
    ", argv[0]);
    					DBG_PRINTF("Usage: %s -l
    ", argv[0]);
    					return -1;
    					break;
    			}
    		}
    	}
    
    	if (!bList && (optind >= argc))
    	{
    		DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>
    ", argv[0]);
    		DBG_PRINTF("Usage: %s -l
    ", argv[0]);
    		return -1;
    	}
    		
    	iError = DisplayInit();
    	if (iError)
    	{
    		DBG_PRINTF("DisplayInit error!
    ");
    		return -1;
    	}
    
    	iError = FontsInit();
    	if (iError)
    	{
    		DBG_PRINTF("FontsInit error!
    ");
    		return -1;
    	}
    
    	iError = EncodingInit();
    	if (iError)
    	{
    		DBG_PRINTF("EncodingInit error!
    ");
    		return -1;
    	}
    
    
    	iError = InputInit();
    	if (iError)
    	{
    		DBG_PRINTF("InputInit error!
    ");
    		return -1;
    	}
    
    
    
    	if (bList)
    	{
    		DBG_PRINTF("supported display:
    ");
    		ShowDispOpr();
    
    		DBG_PRINTF("supported font:
    ");
    		ShowFontOpr();
    
    		DBG_PRINTF("supported encoding:
    ");
    		ShowEncodingOpr();
    
    		DBG_PRINTF("supported input:
    ");
    		ShowInputOpr();
    
    		DBG_PRINTF("supported debug chanel:
    ");
    		ShowDebugOpr();
    		
    		return 0;
    	}
    
    	strncpy(acTextFile, argv[optind], 128);
    	acTextFile[127] = '';
    		
    	iError = OpenTextFile(acTextFile);
    	if (iError)
    	{
    		DBG_PRINTF("OpenTextFile error!
    ");
    		return -1;
    	}
    
    	iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
    	if (iError)
    	{
    		DBG_PRINTF("SetTextDetail error!
    ");
    		return -1;
    	}
    
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    
    	iError = SelectAndInitDisplay(acDisplay);
    	if (iError)
    	{
    		DBG_PRINTF("SelectAndInitDisplay error!
    ");
    		return -1;
    	}
    
    	iError = AllInputDevicesInit();
    	if (iError)
    	{
    		DBG_PRINTF("Error AllInputDevicesInit
    ");
    		return -1;
    	}
    	
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	iError = ShowNextPage();
    	DBG_PRINTF("%s %s %d
    ", __FILE__, __FUNCTION__, __LINE__);
    	if (iError)
    	{
    		DBG_PRINTF("Error to show first page
    ");
    		return -1;
    	}
    
    	DBG_PRINTF("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");
    
    	while (1)
    	{
    
    		if (0 == GetInputEvent(&tInputEvent))
    		{
    			if (tInputEvent.iVal == INPUT_VALUE_DOWN)
    			{
    				ShowNextPage();
    			}
    			else if (tInputEvent.iVal == INPUT_VALUE_UP)
    			{
    				ShowPrePage();			
    			}
    			else if (tInputEvent.iVal == INPUT_VALUE_EXIT)
    			{
    				return 0;
    			}
    		}
    	}
    	return 0;
    }
    

    5.测试代码

    ./show_file -s 24 -d fb -f ./simsun.ttc ./dazhuzai.txt
  • 相关阅读:
    BZOJ2821 作诗(Poetize) 【分块】
    BZOJ2724 蒲公英 【分块】
    Codeforces 17E Palisection 【Manacher】
    BZOJ2565 最长双回文串 【Manacher】
    Codeforces 25E Test 【Hash】
    CODEVS3013 单词背诵 【Hash】【MAP】
    HDU2825 Wireless Password 【AC自动机】【状压DP】
    HDU2896 病毒侵袭 【AC自动机】
    HDU3065 病毒侵袭持续中【AC自动机】
    HDU2222 Keywords Search 【AC自动机】
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/12362149.html
Copyright © 2011-2022 走看看