dimanche 27 mai 2012

Le problème de l'Internet d'aujourd'hui

Internet est ennuyeux. Nous regardons les informations. Nous regardons un nouveau petit chaton sur YouTube, ou nous mettons à jour notre statut. Mais à la différence d'un vrai voyage en Antarctique ou même d'une balade dans le voisinage, il y manquera toujours quelque chose…

Internet est bien lorsque nous cherchons quelque chose de précis, mais qu'en est-il si nous ne savons pas exactement ce que nous recherchons?

Dans la vraie vie, il peut arriver de sortir, faire une promenade, se balader et atterrir dans une petite librairie en bas de la rue. Un tel scénario sur Internet serait celui-ci: nous tapons "librairies" sur Google et nous suivons un lien… Si bien que l'expérience d'Internet de nos jours revient tout juste à avoir les yeux bandés. Nous partons d'un endroit puis nous désirons avancer, nous avons alors besoin d'aide (de la part d'un moteur de recherche ou en connaissant déjà l'adresse du site internet) pour sauter (ou être amené) de l'endroit où nous sommes actuellement, directement vers une prochaine destination. Etant donné que nous avons les yeux bandés, nous perdons la possibilité d'aller réellement d'un endroit à un autre, et nous ne pouvons pas, en plein milieu du chemin, décider d'arrêter juste parce que nous avons envie d'autre chose.

Puisque nous sautons simplement d'un site à un autre, et comme il n'y a aucune distance, c'est comme si voyager de Los Angeles vers la Nouvelle Zélande était la même chose que d'aller à San Francisco. Notre expérience d'utilisateur est un résultat direct de l'endroit que nous visitons, ce qui est logique, mais il manque d'autres éléments comme la longueur du voyage et combien il a été facile ou au contraire fatiguant de s'y rendre.

Donc, d'un côté, Internet aide beaucoup à aller d'un endroit à un autre, et d'un autre côté, il est impossible de faire réellement la route entre les deux sites Internet, d'expérimenter un vrai voyage, ponctué d'endroits intéressants le long du chemin.


L'ingrédient manquant

Quel est donc cet ingrédient qui manque à Internet? Eh bien, nous pouvons l'appeler l'orientation spatiale.
Lorsque nous partons en voyage, nous passons durant le trajet devant plein d'endroits, certains sont intéressants et d'autres moins. Quel est le point commun entre tous ces endroits par lesquels nous transitons, où certains ne valent pas le détour, alors que d'autres sont tellement intéressants que nous décidons d'y passer plusieurs heures ou jours.
La réponse est qu'ils existent tous les deux, qu'ils sont tous les deux .  Donc pour renvoyer le terme "là" sur Internet, nous devons créer une espace similaire au monde réel.
Non. Je ne suis pas en train de parler d'un nouveau jeu de réalité virtuelle... La virtualité correspond à quelque chose qui n'est pas réel, mais Internet est réel. Il ne doit pas devenir un "monde réel" de substitution, mais devrait devenir un monde (ou univers) nouveau et unique.
Certaines des caractéristiques de notre monde sont arbitraires mais en réalité, c'est ce qui rend notre monde excitant, imprévisible et en mutation constante. Beaucoup des choses que nous vivons arrivent "par accident": nous rencontrons quelqu'un par accident, nous découvrons un endroit superbe par accident.
Revenons à l'exemple de la librairie. Lorsque nous avons trouvé cette petite librairie le long du chemin, nous n'avons pas eu besoin de taper "Livres" dans Google. Elle était juste là.
Il y a eu beaucoup de tentatives pour ajouter une dimension "spatiale" aux caractéristiques d'Internet, mais dans la plupart des cas, l'espace était un reflet direct des données prises dans le monde réel. Google Street View nous permet par exemple de voyager comme si nous étions vraiment en train de voyager.

Mais Internet mérite sa propre existence; il mérite son propre espace. Il est utile de simuler le voyage, le vol, la conduite et la rencontre des personnes dans notre région, mais ne serait-il encore pas plus facile de voyager réellement via Internet, dans la réalité, et non pas dans une simulation d'une autre réalité?

Pour que cela arrive, nous devons attribuer aléatoirement une place dans l'espace aux sites Internet, (qui peut être basée sur le premier arrivé, premier servi), mais avec la possibilité de bouger "physiquement" d'un endroit à un autre, comme lors d'une promenade.


Voyager via Internet

Projeter Internet dans un espace nouveau et unique, avec les distances, les chemins et sa propre orientation spatiale, dévoilera le vrai potentiel d'Internet . Pensons-y ainsi : pourquoi sommes-nous tellement dépendant des moteurs de recherche (i.e. Google …)? Pourquoi ne pouvons-nous pas simplement naviguer sur Internet?

La création d'un tel espace doit commencer par l'attribution pour cet espace de caractéristiques aléatoires, qui par la suite deviendront plus importantes. Cela sera comme recenser la population il y a plusieurs millions d'années comparé à aujourd'hui, alors qu'il y a une différence significative entre vivre à un endroit par rapport à un autre, ou trouver une maison dans le centre-ville par rapport à la banlieue.

De plus, il doit y avoir plus d'une façon de voyager. Pas simplement en tapant sur Google, mais en ayant la possibilité sans fin d'être emerveillé. En guise de résultat, l'expérience Internet nous incitera à visiter des endroits que nous n'avions pas prévu de visiter. Cela permettra ainsi de visiter des endroits juste parce qu'ils sont situés à côté d'un autre endroit dans lequel nous souhaitions nous rendre au départ, et le terme "situé à côté" devra être implémenté en utilisant un nouveau système de mapping et non pas en reflétant un système géographique existant importé du monde réel.

Cela donnera à Internet ce qu'il mérite - sa propre existence en tant qu'univers.
Bien sûr, même si nous sommes tous ravi de facilement sauter de LA vers la Nouvelle Zélande en l'espace d'une seconde, les vieilles habitudes de l'utilisation d'Internet seront toujours disponibles, et seront utilisées comme auparavant, mais il est temps d'ajouter cet ingrédient manquant à Internet afin qu'il devienne un véritable univers à part entière.


Conseils supplémentaires

L'univers qui est enfermé dans l'existence d'Internet possède beaucoup de choses en commun avec notre propre univers, ce qui donne des idées comme remplir le manque d'orientation spatiale, mais il y a aussi un gros potentiel pour les caractéristiques qui ne peuvent pas faire partie de notre propre monde, tel que le voyage dans le temps.
La navigation sur Internet peut être filtrée par une certaine période ou une certaine année (par exemple, le 20è siècle). Si la navigation sur Internet peut devenir une expérience similaire aux voyages et à l'exploration de nouveaux mondes, de tels filtres peuvent faire de cette expérience un voyage dans le temps avec une machine à remonter dans le temps.

Nouveaux modèles de développement

De plus, une variété de moyens de transport sera disponible pour le voyageur d'Internet qui non seulement arrêtera sa dépendance négative aux moteurs de recherche, mais qui choisira aussi l'option de sélectionner sa façon de voyager. Cela créera de nouveaux modèles d'affaires: rapides, lents, directs ou ayant plusieurs arrêts le long du trajet. En parlant des nouveaux modèles d'affaires, tous les modèles d'affaires reliés à Internet aujourd'hui sont basés sur le nombre de visites, et il y a là une nouvelle opportunité de créer de nouveaux modèles d'affaires basés sur le voyage réel d'un site internet vers un autre. Basé sur de tels modèles, l'audience d'un site serait par défaut notre voisinage (dans un rayon autour de nous) et donc, pourrait être fournie gratuitement, alors qu'il pourrait y avoir des charges s'il s'agit d'un voyage plus long basé sur la distance Internet qui reflète la nouvelle façon dont Internet sera lié.

Le Quartier

En ajoutant l'orientation spatiale à Internet, et en rassemblant les sites Internet et les pages par endroits, comme les quartiers, les villes, les états, les pays et les continents, une "ville Internet" typique aurait des sites Internet de nature différente, "habitant" l'un à côté de l'autre. Ces sites pourront être une librairie, une agence de voyage (la "zone commerciale" de notre ville), plusieurs blogs personnels (la "zone résidentielle" de notre ville), des musées, des agences d'informations, etc. qui partageront tous le même quartier. Les vraies personnes et organisations derrière ces sites Internet, même si ces sites Internet seront liés à la même ville, pourront venir de partout dans le monde. A l'inverse des entreprises qui visent à lier l'activité sur Internet à une localisation géographique, pour dire par exemple à l'utilisateur final qui est dans son ou sa zone (amis, restaurants, etc.), cette idée sera de permettre à Internet d'avoir son propre domaine géographique, avec des endroits, des distances, et la possibilité de voyager et de les explorer, peu importe l'endroit où nous sommes dans le monde réel.
Donc ces villes auront ces sites les uns à côté des autres en résultat de "l'offre et de la demande". D'abord, l'univers entier sera libre de s'installer, et comme les vieux explorateurs, les gens auront l'opportunité de s'installer n'importe où et d'établir des communautés à côté des autres personnes et entreprises, mais l'hétérogénéité (qui est l'idée centrale de cet article) apportera toutes sortes d'entreprises, d'affaires et de personnes vers la même communauté.
Dans le monde réel, une personne peut ouvrir un salon de coiffure à côté d'un webcafé ou d'un bar, même s'ils n'ont rien en commun à l'exception d'habiter arbitrairement l'un à côté de l'autre. Habiter l'un à côté de l'autre sans partager le même contenu, public, pays d'origine et même langue… tout cela ne devrait pas empêcher les sites Internet d'habiter dans le même quartier Internet.

La possibilité d'avoir ces sites Internet "près de" ou "à côté de" avec la possibilité de fournir aux utilisateurs finaux l'expérience de l'émerveillement et du voyage à travers Internet avec moins de dépendance vis-à-vis des moteurs de recherche représente basiquement ce dont manque Internet aujourd'hui.

Les secrets pour développer Rashumon

Lorsque j'ai développé Rashumon, il n'y avait pas de support intégré pour le texte multilingue / bi-directionnel et j'ai dû le développer from scratch.

Etat de l'existant

Entre 1989 et 1994 j'ai développé Rashumon, le premier traitement de texte graphique multilingue pour l'Amiga. Rashumon présentait alors des caractéristiques uniques:
  • Sélection Mulitple de texte (sélectionnant en même temps des parties non continues de texte)
  • Générateur de Table
  • Support multiple de cartes index (jusqu'à 5 simultanément)
  • Chercher et remplacer avec les filtres de couleur, de style et de police 
    Rashumon - Search / Replace
  • Chaînes multilingues à utiliser pour créer et renommer des fichiers, des dessins, etc.
  • Import et export de fichiers ASCII multilingues de et vers PC et MAC
  • Ecran ultra plat défilant
  • Support graphique IFF (import et export).
  • Accès direct à chacun des 256 caractères pour chaque police.

Utiliser le code

Les échantillons de code utilisés dans cet article sont issus du code source de Rashumon;  ils peuvent être lus par n'importe quel compilateur C++, quand bien même ils ont été mis au point d'abord et avant tout pour Amiga Aztec C compiler.

Points intéressants

De nos jours, nous avons tendance à oublier un peu de la complexité qui faisait partie du codage d'il y a 20 ans; aujourd'hui tout est intégré dans n'importe quelle partie de n'importe quel système d'exploitation SDK, y compris: modification bi-directionnelle, modification de texte en général, défilement du texte et  retour à la ligne. A l'époque (1989), développer un Word graphique multilingue pour Amiga était une gageure et avait requis de la programmation de ce qui aujourd'hui ferait partie d'un véritable système d'exploitation.

Développer Rashumon

L'Amiga était et est toujours un bon ordinateur, présentant de grandes capacités,  en particulier concernant le son et la vidéo. Cependant, il manquait des éléments basiques comme  une boîte de dialogue de recherche de fichiers, sans mentionner le support pour les langues se lisant de droite à gauche. Aujourd'hui, tous les systèmes d'exploitation contiennent les éléments principaux requis pour accepter la modification de texte multilingue. Le texte est stocké dans l'ordre où il a été tapé, et affiché à l'envers lorsqu'il s'agit d'une langue se lisant de droite à gauche. Cela le rend simple et facile à modifier et à manipuler, étant donné que le stockage reflète l'ordre logique du flux de texte. Auparavant, il fallait au contraire développer tous ces blocs, et cela rendait mon traitement de texte trop lent, car j'affichais le texte différemment de la façon dont il était stocké. En lieu et place de cela, j'ai donc décidé de développer un outil de retour à la ligne. Le retour à la ligne désigne un mécanisme qui permet de couper des lignes sans couper les mots. A l'inverse d'une vieille machine à écrire, où vous arriviez à la fin de la ligne, et parfois cassiez un mot au milieu, les traitements de texte peuvent déplacer le dernier mot tapé vers la prochaine ligne, dans le cas où il n'y aurait pas assez de place pour celui-ci dans la ligne actuelle. Cela devient encore plus complexe lorsque vous avez affaire à des polices proportionnelles, où chaque caractère possède sa propre largeur, et lorsque vous autorisez la combinaison de plusieurs polices. Tout cela ne faisait pas partie d'une API de haut niveau, mais nécessitait le calcul de la longueur prévisionnelle d'un texte, en pixels, en prenant compte de chaque largeur de caractère basée sur le caractère et sur la police, (gras, italique) et la taille utilisée, en plus des marges sélectionnées. Donc même si nous ne nous occupions que d'un sens de modification(de gauche à droite), c'était tout de même compliqué à développer from scratch. Pour bien comprendre, voici la façon de calculer la longueur d'une ligne donnée que j'ai écrite:

int LLen=(mode==GRAPHICS)?ln->Len:(ln->CharLen=strlen(ln->Txt))*8;

Comme vous pouvez le voir, il y a un scénario simple où le "mode" n'est pas "GRAPHICS", et la longueur est alors calculée en fonction du nombre de caractères multiplié par 8 (qui est la longueur d'un caractère lorsqu'une police mono-espace est utilisée). Concernant la modification d'un texte bi-directionnel en utilisant des polices proportionnelles et multiples, c'est plus compliqué même pour insérer un simple caractère:

// C'est une règle pour ajouter un caracère simple, en partant du code source Rashumon

static put_char(wrap,chr)
BOOL wrap;
UBYTE chr;
{
       UBYTE c[2];
       BOOL update=FALSE;

       c[1]='\0';
       c[0]=chr;
       if(ENGLISH_H) // Texte de gauche à droite
       {
              if(chr>='a' && chr<='z' && map[Header->format >> 11]<2) chr=ucase(chr);
              if(Header->Insert || !HCL->Txt[CR])
              {
                     if(!wrap && HCL->Len+font_width(HCL,CR)>HCL->MaxLen) return();
                     char_insert(HCL,c[0],CR);
                     HCL->CharLen++;
                     CR++;
                     HCL->Len+=font_width(HCL,CR-1);  
// Ici nous ajoutons la taille additionnelle de la ligne globale
// taille en pixels
                     HCL->CursLen+=font_width(HCL,CR-1);
              }
              else /* OVERWRITE IN ENGLISH */
              {
                     // Maintenant nous traitons le mode Overwrite
                     HCL->Txt[CR]=c[0];
                     HCL->Format[CR]=Header->format;
                     if(c[0]==9)
                     {
                           SetFlag(HCL->Format[CR],TAB);
                           HCL->Txt[CR]=SPACE_CHR;
                           SetFlag(MD,TABS);
                     }
                     CR++;
                     calc_charlen(HCL);
                     calc_all(HCL);
                     Clear(HCL);
              }
       }
       else
       // Mode Hebreu ( ou de droite à gauche)
       {
              if(!Header->Insert && CR)
              {
                     CR--;
                     HCL->CursLen-=font_width(HCL,CR+1);
                     HCL->Txt[CR]=c[0];
                     HCL->Format[CR]=Header->format;
                     if(c[0]==9)
                     {
                           SetFlag(HCL->Format[CR],TAB);
                           HCL->Txt[CR]=SPACE_CHR;
                           SetFlag(MD,TABS);
                     }
                     calc_all(HCL);
                     Clear(HCL);
              }
              else
              {
                     if(!wrap && HCL->Len+font_width(HCL,CR)>HCL->MaxLen) return();
                     char_insert(HCL,c[0],CR);
                     HCL->Len+=font_width(HCL,CR);
                     HCL->CharLen++;
              }
       }
       if(HCL->Mode & TABS) calc_all(HCL);
       if(c[0]!=SPACE_CHR && fonts[Header->format >> 11]->tf_YSize>LH(HCL))
       {
              HCL->LineHeight=Header->LineHeight=fonts[Header->format >> 11]->tf_YSize;
              HCL->BaseLine=Header->BaseLine=fonts[Header->format >> 11]->tf_YSize-fonts[Header->format >> 11]->tf_Baseline;
              update=TRUE;
       }
       else
       if(c[0]==SPACE_CHR && HCL->prev && !(HCL->Mode & PAR) && wrap)
       {
              WrapLine(HCL->prev,!(update));
       }
       if(HCL->Len<=HCL->MaxLen && !(update))
       {
              showtext(HCL);
              SetCursor();
       }
       else
       if(wrap)
              FixLine(HCL,!update);

       if(update)
              update_lh(HCL,TRUE);


}


L'étape suivante consistait à réaliser un retour à la ligne pour les lignes bi-directionnelles. Comme je l'ai expliqué, les lignes étaient affichées telles qu'elles étaient stockées en mémoire. Le texte "abc???" était stocké exactement tel qu'il avait l'air. Rashumon utilisait des caractères double octets, signifiant que chaque caractère était stocké en utilisant 2 octets. C'était avant que l' UNICODE soit inventé, et donc le premier octet était suffisant pour stocker n'importe quel caractère dans n'importe quelle langue acceptée. A l'époque, les caractères ASCII avaient deux formes, une forme utilisait les valeurs de 0 à 127 et la forme étendue utilisait  les valeurs de 0 à 255. J'utilisais la forme étendue, et je devais décider où placer les langues de droite à gauche. 

Il n'y avait pas de standard pour les langues de droite à gauche. IBM a utilisé des places de 128 à 154, mais j'ai trouvé cela problèmatique et j'ai choisi les places démarrant à 224, ce qui semble le bon choix aujourd'hui, car c'est identique à la façon dont les langues de droite à gauche sont représentées via l'utilisation de l'encodage double octets. Ainsi, si j'ouvre une disquette de 1989 (fichier .ADF), tous les documents Rashumon en Hébreu possèderont un encodage correct. 

Concernant le 2ème octet, il était utilisé pour stocker la couleur du caractère (3 types, ce qui fait jusqu'à 8 couleurs), les caractéristiques de la police (GrasItalique et souligné, ou toute combinaison entre les 3), le langage (droite à gauche ou gauche à droite) et la police, en indiquant un sommaire de cette police dans une  liste locale créée à partir de la liste entière des polices utilisées pour chaque document.

/* Structure de ligne */
#define COLOR_BIT_1 1             /* 1  */
#define COLOR_BIT_2 2             /* 2  */
#define COLOR_BIT_3 4             /* 3  */
#define UNDL 8                    /* 4  */
#define BOLD 16                   /* 5  */
#define ITAL 32                   /* 6  */
#define SELECT 64          /* 7  */
#define LANG 128           /* 8  */
#define TAB 256                   /* 9  */
#define UNUSED_1 1024             /* 10 */
#define UNUSED_2 2048             /* 11 */
#define FONT_BIT_1 4096    /* 12 */
#define FONT_BIT_2 8192           /* 13 */
#define FONT_BIT_3 16384   /* 14 */
#define FONT_BIT_4 32768   /* 15 */
#define FONT_BIT_5 65536   /* 16 */


Mappage de clés et encodage

Le mappage de clés (key mapping) était utilisé en tant que tableau de tous les caractères par places commençant de "1" à la fin du tableau. Voici une autre partie prise du code source Rashumon, où les mappages sont définis:

/* CARTES ANGLAISES ET HEBREUSES */
unsigned char regmap[] =
       ";1234567890-=\\ 0/'-˜€ˆ...??"[] 123(tm)ƒ‚‹'‰‡ŒŠ",  456 †'?„?Ž-š•. .789 ";

unsigned char engmap[] =
       "`1234567890-=\\ 0qwertyuiop[] 123asdfghjkl;'  456 zxcvbnm,./ .789 ";

unsigned char shiftmap[] =
       "~!@#$%^&*()_+| 0QWERTYUIOP{} 123ASDFGHJKL:\"  456 ZXCVBNM<>? .789 ";

unsigned char shiftrus[] =
       "~!@#$%^&*()_+| 0°¶?±³¸´¨(r)¯{} 123 ²£¥¦§(c)׫:\"  456 ¹·¢µ¡­¬<>? .789 ";

unsigned char rusmap[] =
       “`1234567890-=\\
0׀ײִׁ׃״װָ־ֿ[] 123ְֳֵֶַֹֺֻׂ;’  456 ׳ֲױֱּֽ,./ .789 “;




Comme vous pouvez le voir, "regmap" est l'encodage hébreu, "engmap" est pour le texte latin, "shiftmap" est pour les caractères tapés avec le bouton SHIFT, et il y avait aussi une carte index pour le Russe (et par la suite, une pour l'Arabe aussi, grâce à John Hajjer, de Chicago, qui a passé beaucoup de temps pour m'aider à publier une version Arabe).
Le changement entre les deux sens a été fait en utilisant une règle unique avec deux versions : de gauche à droite et de droite à gauche:

En appuyant sur la flèche, cela changeait le sens de la modification.

Défilement du texte

Même les choses les plus évidentes comme le défilement ont du être inventés dans le temps. Cela comprend l'établissement du nombre de lignes de texte à afficher, en fonction de la taille de fenêtre actuelle (la fenêtre Amiga avait la possibilité d'être redimensionnée par l'utilisateur final, ainsi que maximisée et réduite), affichant une barre de défilement, et calculant la taille de la jauge de la barre de défilement qui devait être proportionnelle au mouvement possible et au défilement disponible.

scroll(ln,lines)
struct Line *ln;
int lines;
{
       register SHORT distance,
                     top=TOP,
                     bot=BOT;
#if DEBUG
       printf("BEFORE: top=%ld (%ld <> TOP=%ld) ",
                     Header->top->num,
                     Header->top->y,TOP+Header->shift);
       printf("bottom=%ld (%ld <> BOT=%ld)\n",
                     Header->bottom->num,
                     Header->bottom->y+LH(Header->bottom),BOT+Header->shift);
#endif
       if(lines>0)
       {
              distance=Header->bottom->next->y+LH(Header->bottom->next)-Header->shift-Header->Height;
              Header->shift+=distance;
              while(Header->top->y<Header->shift)
                     Header->top=Header->top->next;
              Header->bottom=Header->bottom->next;
       }
       else
       {
              distance=-(Header->shift-Header->top->prev->y);
              Header->shift+=distance;
              Header->top=Header->top->prev;
              while(Header->bottom->y+LH(Header->bottom)>Header->Height+Header->shift)
                     Header->bottom=Header->bottom->prev;
       }
       if(distance<100)
              ScrollRaster(rp,0,distance,0,TOP,640,BOT);
       else
              calc_top_bottom(TRUE,0,0);
#if DEBUG
       printf("AFTER: top=%ld (%ld <> TOP=%ld) ",
                     Header->top->num,
                     Header->top->y,TOP+Header->shift);
       printf("bottom=%ld (%ld <> BOT=%ld)\n",
                     Header->bottom->num,
                     Header->bottom->y+LH(Header->bottom),BOT+Header->shift);
#endif
}


Retour à la ligne de texte bi-directionnel

Mais maintenant revenons au retour à la ligne du texte bi-directionnel. A la base, l' algorithme, développé par Tamer Even –Zohar, son mari Nimrod et moi, était basé sur l'examen d'une ligne donnée et si elle était plus longue que la taille entre les deux marges (calculant la largeur de la ligne en pixels, prenant en compte chaque caractère, basé sur ses caractéristiques indépendantes), nous devions en retirer le dernier mot, puis vérifier de nouveau la nouvelle longueur, et ainsi de suite, jusqu'à ce que la ligne soit dans la largeur des marges. La première question à poser est où est le "dernier" mot? Si c'est un paragraphe de droite à gauche, le dernier mot apparaîtra en premier, dans le tampon. Dans un tel cas, j'ai utilisé la fonction suivante, qui en réalité mesure la taille  (en pixels) du premier mot dans un tampon donné. Les calculs suivants sont basés sur une police à espace simple, ce qui est déjà assez compliqué…

/* returns the len of the first word in s */
#define BLNK(c)      ((c)==' ' || (c)=='\n')
first_wordlen(s,margin,blnks1,blnks2)
char *s;
int margin, *blnks1, *blnks2;
{
  register int i, j;
/*     for (i=strlen(s)-1; BLNK(s[i]) && i; i--);
       if ((strlen(s)-(i+1))>1)  s[i+2] = '\0'; */
       for (i=margin; BLNK(s[i]) && s[i]; i++);
       *blnks1 = i;
       for (; !(BLNK(s[i])) && s[i]; i++);
       for (j=i; BLNK(s[j]) && s[i]; j++);
       *blnks2 = j-i;
       return(i);
}


Si la ligne est une ligne de la gauche vers la droite, une fonction différente était utilisée:

last_wordlen(s,blnks1,blnks2,maxlen)
char *s;
int *blnks1, *blnks2, maxlen;
{
  register int i, j;
       if (!strlen(s)) return(0);
       for (i=strlen(s)-1; BLNK(s[i]) && i; i--);
       if (i==0) return(0);
       *blnks1 = (strlen(s)-(i+1));
       for (i=min(maxlen,strlen(s)-1); BLNK(s[i]) && i; i--);
       for (; !(BLNK(s[i])) && i; i--);
       for (j=i; BLNK(s[j]) && j; j--);
       i++;
       *blnks2 = i - j;
       return(strlen(s) - i);
}


Bien sûr nous ne retirons pas que le dernier mot d'une ligne, mais nous replaçons aussi le premier mot de la ligne suivante, lorsqu'il y a de l'espace disponible (par exemple, si le premier mot dans la ligne actuelle est supprimé, et que de l'espace devient disponible), alors un autre bloc de construction replacerait le mot suivant (en partant du début de la ligne suivante) à la fin de la ligne actuelle.

/* copies first word of length len & trailing blanks blnks fron s2 to s1 */
copy_first(s1,s2,len,blnks)
char *s1,*s2;
int len,blnks;
{
       append(s2,s1,strlen(s1)+len+(blnks ? 1 : 0));
       delete1(s2,0,len+(blnks ? 1 : 0));
}


Dans Rashumon, le sens du texte du paragraphe était automatiquement calculé en examinant l'encodage de chaque caractère sur chaque ligne, et en déterminant quel sens dominait. Tout en réfléchissant avec Tamar Even Zohar et son mari Nimrod, nous avons compris que même le caractère d'espace " " peut avoir un sens, et nous devions décider si nous souhaitions avoir le caractère d'espace Hébreu en plus du caractère Latin . Et bien, cette demande est devenue une "obligation", car elle nécessitait un retour à la ligne  des paragraphes avec plusieurs langues combinées. Par exemple: 

"This is an example of a paragraph with opposed direction languages. ו דוגמה לפסקה עם שילוב של שתי שפות עם כיוונים מנוגדים" 

La vidéo ci-dessous montre comment le texte bi-directionnel est modifié par Rashumon.

Désormais, si vous changez les marges, quel mot "sautera" à la ligne suivante, ou "sautera" en arrière vers la ligne actuelle? La seule façon de le savoir, c'est en connaissant le sens de chaque caractère (soit de droite à gauche ou de gauche à droite), y compris les caractères spéciaux comme les tabulations, les espaces, les virgules, etc. Rashumon peut être télécharger sur Aminet sur this link.
An Article about Rashumon (UK)

Pour aller plus loin

Mon Blog (Hebrew)
Mon Blog (English)