Logo Search packages:      
Sourcecode: acon version File versions  Download package

render.c

/*
 * acon a utility to facilitate the right to left writing
 * Copyright 1999 Ahmed Abdel-Hamid Mohamed <ahmedam@mail.usa.com>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 * Ave, Cambridge, MA 02139, USA.
 *
 */
 
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "acon.h"
#include "child.h"
#include "arabicfont.h"
#include "render.h"

int direction=0;  /*0=left to right,1=right to left*/
int ypos;               /*current line to be processed*/
int usehendinums=0;

struct Sisocp isocp[260];
struct Slforms lforms[260];
struct Sbraces braces[100];
struct Spairs pairs[100];
unsigned int hendinums[12];

char newline[200];
char newlinegroub[200];

unsigned char tohendinums(unsigned char chr)
{
      if(chr>='0' && chr<='9')return (unsigned char)hendinums[chr-'0'];
      return chr;
}

/*Return the new Alef glyph which appears after Lam*/
unsigned char changepair(unsigned char *old1,unsigned char *old2)
{
      int i;
      i=0;
      while(pairs[i].old1!=255)
      {
            if(pairs[i].old1==*old1 && pairs[i].old2==*old2)
            {
                  *old1=pairs[i].new1;
                  return *old2=pairs[i].new2;
            }
            i++;
      }
      return *old2;
}

unsigned char changebraces(unsigned char chr)
{
      int i=0;
      while(braces[i].in!=255){
            if(braces[i].in==chr)return braces[i].out;
            i++;
      }
      return chr;
}

struct {unsigned char lines, cols, x, y;} scrn; /*carries console size and current cursor position*/

int getlform(unsigned char chr)
{
   int i;
   i=0;
   while(lforms[i].alone!=255)
   {
      if(lforms[i].chr==chr)return i;
      i++;
   }
   return 255;
}

int groub;

int findiso(unsigned char chr)
{
      int i=0;
      groub=0;
      while(groub!=255){
            while(isocp[i].iso!=255 && isocp[i].iso!=chr)
                  i++;
            if(isocp[i].iso==255)groub=isocp[i].cp;
            if(isocp[i].iso==chr)break;
            i++;
      }
      if(groub==255)return 255;
      return isocp[i].cp;
}

unsigned char isotocp(unsigned char chr)
{
      unsigned char c;
      if((c=findiso(chr))==255)return chr;
      return c;
}

void processlineLTR(unsigned char *line,int len)
{
      int i,z,loc=0,change=0,tochange=0,locn,tmp,startofline=1;
      char buf[400];
      unsigned char curloc[200];
      int lang=0; /*0=english 1=arabic*/

      for(i=0;i<len;i+=2)
      {
            newline[i/2]=isotocp(line[i]);
            newlinegroub[i/2]=groub;
            curloc[i]=200;
      }
      
      for(i=0;i<len;i+=2)
      {
            groub=tmp=newlinegroub[i/2];
            if(change>i){
                  if(tochange)lang=0;
            }
            else if(groub==6 || groub==5 || groub==1 || groub==255)
            {
                  for(z=i+2;z<len;z+=2)
                  {
                        groub=newlinegroub[z/2];
                        if((groub>1 && groub<5) || groub==7)break;
/*                      if(line[z]>0xc0 && line[z]<0xf3)break;*/
                        if(groub==10 || (line[z]>='A' && line[z]<='Z') || (line[z]>='a' && line[z]<='z'))
                              break;
                  }
                  tochange=0;
                  change=z;
                  if(z==len || groub==10 || (line[z]>='A' && line[z]<='Z') || (line[z]>='a' && line[z]<='z'))
                        tochange=1,lang=0;
            }
            if(lang)
                  newline[i/2]=changebraces(newline[i/2]);

            groub=tmp;
            if(groub==10)
                  startofline=1;
            else if(line[i]!=' ')
                  startofline=0;

        if((line[i]>='A' && line[i]<='Z') || (line[i]>='a' && line[i]<='z') )
            lang=0,loc=i;
        if(lang==0 && ((groub>1 && groub<5) || groub==7 || line[i]==0xa0))
        {
           lang=1;
           loc=i;
           
           buf[loc]=ltransform(line[i],i/2);
           buf[loc+1]=line[i+1];
             curloc[loc/2]=i/2;
        }
        if(groub==10 || !lang || (startofline && line[i]==' '))
        {
           buf[i+1]=line[i+1];
           buf[i]=(line[i]>127?ltransform(line[i],i/2):(usehendinums==1?tohendinums(line[i]):line[i]));
           loc=i;
             curloc[loc/2]=i/2;
        }
        else if(groub!=6)
        {
            memmove(buf+loc,buf+loc-2,400-1-loc);
            memmove(curloc+loc/2,curloc+loc/2-1,(len-loc-1)/2);
                  buf[loc]=ltransform(line[i],i/2);
                  buf[loc+1]=line[i+1];
                  curloc[loc/2]=i/2;
                  locn=loc;
        }
        else{
           memmove(buf+locn,buf+locn-2,400-1-locn);
           memmove(curloc+locn/2,curloc+locn/2-1,(400-locn-1)/2);
           buf[locn]=ltransform(line[i],i/2);
           buf[locn+1]=line[i+1];
             curloc[locn/2]=i/2;
           locn+=2;
            }
      }
      memcpy(line,buf,len);  
      if(scrn.y==ypos)
            for(i=len/2;i>=0;i--)
                  if(curloc[i]==scrn.x)
                        {scrn.x=i;break;}

}

void processlineRTL(unsigned char *line,int len)
{
   int i,z,loc=0,tmp,startofline=1,tochange=0,change=0;
   char buf[400];
   char curloc[200];
   int lang=1;    /*0=english 1=arabic*/

      for(i=0;i<len;i+=2)
      {
            newline[i/2]=isotocp(line[i]);
            newlinegroub[i/2]=groub;
            curloc[i]=0;
      }
      
   for(i=0;i<len;i+=2)
   {

            groub=tmp=newlinegroub[i/2];
            if(change>i){
                  if(tochange)lang=1;
            }
            else if(groub==6 || groub==5 || groub==1 || groub==255){
                  for(z=i;z<len;z+=2){
                        groub=newlinegroub[z/2];
                        if((groub>1 && groub<5) || groub==7)break;
/*                      if(line[z]>0xc0 && line[z]<0xf3)break;*/
                        if(line[z]==179 || (line[z]>='A' && line[z]<='Z') || (line[z]>='a' && line[z]<='z'))break;
                  }
                  tochange=0;
                  change=z;
                  if(z==len || groub==10 || (/*line[z]>0xc0 && line[z]<0xf3*/groub>1 && groub<5))tochange=1,lang=1;
            }

            if(lang)newline[i/2]=changebraces(newline[i/2]);

            groub=tmp;
            if(groub==10)startofline=1;
            else if(line[i]!=' ')startofline=0;
            
            if((groub>1 && groub<5) || groub==7 || line[i]==0xa0)lang=1;
        if(lang==1 && ((line[i]>='A' && line[i]<='Z') || (line[i]>='a' && line[i]<='z') ))
        {
            lang=0;
            loc=i;
            buf[len-loc+1-2]=line[i+1];
            buf[len-loc-2]=line[i];
              curloc[(len-loc-2)/2]=i/2;
        }
        if(groub!=6 && (groub==10 || (startofline && line[i]==' ') || lang)){
            buf[len-i-2]=ltransform(line[i],i/2);
            buf[len-i+1-2]=line[i+1];
            loc=i+2;
              curloc[(len-i-2)/2]=i/2;
        }
        else{
            memmove(buf,buf+2,len-loc-2);
            memmove(curloc,curloc+1,(len-loc-2)/2);
              curloc[(len-loc-2)/2]=i/2;
/*            buf[len-loc-2]=ltransform(&line[(i>1?i-2:0)],line[i],&line[i+2]);*/
                  buf[len-loc-2]=(line[i]>127?ltransform(line[i],i/2):((usehendinums==2 && lang) || usehendinums==1?tohendinums(line[i]):line[i]));
            buf[len-loc+1-2]=line[i+1];
        }
   }
   memcpy(line,buf,len);

   if(scrn.y==ypos)
            for(i=len/2;i>=0;i--)
                  if(curloc[i]==scrn.x)
                        {scrn.x=i;break;}
}

unsigned char lastchr;
void processline(unsigned char *line,int len)
{
      int i;
      lastchr=0;
      if(!direction)processlineLTR(line,len);
      else processlineRTL(line,len);
      for(i=0;i<len;i+=2)
            changepair(&line[i+2],&line[i]);

}

unsigned char ltransform(unsigned char y,int charnum)
{
   int xg,zg,z;

   /*Lam-Alef pair*/
   y=newline[charnum];
   groub=newlinegroub[charnum];
   if(usehendinums)
            y=tohendinums(y);
/*   y=changepair(lastchr,y);*/
   lastchr=y;
   
   if(getlform(y)==255)return y;
   if(groub!=2 && groub!=3 && groub!=4)return y;

   /*if the character is tashkil test the neibourhood*/
      z=charnum-1;
   do{
      xg=newlinegroub[z];
      if(xg==4)z--;
   }while(xg==4);
      z=charnum+1;
   do{
      zg=newlinegroub[z];
      if(zg==4)z++;
   }while(zg==4);
   if(xg==2 && (zg==2 || zg==3))return lforms[getlform(y)].middle;
   if(xg==2)return lforms[getlform(y)].last;
   if(zg==2 || zg==3)return lforms[getlform(y)].first;
   return lforms[getlform(y)].alone;
}

int getmaxx(void)
{
      return scrn.cols;
}
int getmaxy(void)
{
      return scrn.lines;
}

int drawscrn(int ttyvc,int consolevc)
{
      unsigned int i;
      static unsigned char oldx=255,oldy;
      char line[400];
   
      lseek(consolevc,0,SEEK_SET);
      lseek(ttyvc,4,SEEK_SET);

      if(read(consolevc,&scrn,4)!=4){
            printf("error reading virtual console memory to get size");
            return 1;
      }
            
      line[0]=0,line[scrn.cols*2]=0,line[scrn.cols*2+2]=0;
      if(oldx==255)oldx=scrn.x,oldy=scrn.y;
      
#if __DEBUG__
   printf("lines %d  cols %d \n",(int)scrn.lines,(int)scrn.cols);
#endif

      for(i=0;i<scrn.lines;i++)
      {
        ypos=i;
            if(read (consolevc,line+2,((size_t)scrn.cols)*2)!=scrn.cols*2){
            printf("error reading virtual console memory");
            return 1;
        }
        processline (line+2,((int)scrn.cols)*2);
        if(write(ttyvc,line+2,((size_t)scrn.cols)*2)!=scrn.cols*2){
            printf("error writing to virtual console memory");
            return 1;
        }
        processkey(0);
      }
      lseek(ttyvc,0,SEEK_SET);
      write(ttyvc,&scrn,4);
      oldx=scrn.x,oldy=scrn.y;
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index