home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / educatio / xcoral16.zip / TEXT_CUR.C < prev    next >
C/C++ Source or Header  |  1993-01-15  |  12KB  |  564 lines

  1. /*
  2. ** Copyright 1989, 1992 by Lionel Fournigault
  3. **
  4. ** Permission to use, copy, and distribute for non-commercial purposes,
  5. ** is hereby granted without fee, providing that the above copyright
  6. ** notice appear in all copies and that both the copyright notice and this
  7. ** permission notice appear in supporting documentation.
  8. ** The software may be modified for your own purposes, but modified versions
  9. ** may not be distributed.
  10. ** This software is provided "as is" without any expressed or implied warranty.
  11. **
  12. **
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include <strings.h>
  19.  
  20. #include "text.h"
  21.  
  22. static void GetCurrentXY ();
  23. static int MyTextWidth ();
  24. extern Display *dpy;
  25.  
  26. /*
  27. **    Function name : TextCursorOn
  28. **
  29. **    Description : Allume le curseur.
  30. **
  31. **    Input : Le text courant.
  32. **    Ouput :
  33. */
  34. void TextCursorOn ( text )
  35.     Text    *text;
  36. {
  37.     int x, y;
  38.     char c;
  39.     register int width;
  40.  
  41.     SetLinesTable ( text );
  42.     (void) GetCurrentXY ( text, &x, &y, &c );
  43.  
  44.     if ( (c == '\t') || (c == NULL) || (c == '\n') ) 
  45.         width = text -> char_width_ave;
  46.     else 
  47.         width = XTextWidth ( text -> font, &c, 1 );
  48.  
  49.     text -> x_pos = x;
  50.     text -> y_pos = y;
  51.     text -> cursor_width = width;
  52.  
  53.     if ( text -> cursor_stat == ON )
  54.         return;
  55.  
  56.     if ( text -> mouse_in == True ) {
  57.         if ( text -> cursor_stat == FREESE )
  58.             UnFreeseTextCursor ( text );
  59. #ifdef DEBUG
  60.         (void) fprintf ( stderr, "Cursor On\n" );
  61. #endif DEBUG
  62.         XFillRectangle ( dpy, text -> window,text -> Igc,
  63.             x, y, text -> cursor_width, text -> font_height );
  64.         text -> cursor_stat = ON;
  65.     }
  66.     else
  67.         FreeseTextCursor ( text );
  68. }
  69.  
  70.  
  71. /*
  72. **    Function name : FreeseTextCursor
  73. **
  74. **    Description : Gele le curseur.
  75. **    Input : Le text courant.
  76. **    Ouput :
  77. */
  78. void FreeseTextCursor ( text )
  79.     Text *text;
  80. {
  81.  
  82. #ifdef DEBUG
  83.     (void) fprintf ( stderr, "FreeseCursor x = %d y = %d\n",
  84.         text -> x_pos, text -> y_pos);
  85. #endif DEBUG
  86.     if ( text -> cursor_stat != OFF )
  87.         return;
  88.  
  89.     XDrawRectangle ( dpy, text -> window, text -> Igc,
  90.         text -> x_pos, text -> y_pos,
  91.         text -> cursor_width, text -> font_height );
  92.  
  93.     text -> cursor_stat = FREESE;
  94. }
  95.  
  96.  
  97. /*
  98. **    Function name : UnFreeseTextCursor
  99. **
  100. **    Description : Degele le curseur.
  101. **    Input : Le text courant.
  102. **    Ouput :
  103. */
  104. void UnFreeseTextCursor ( text )
  105.     Text *text;
  106. {
  107. #ifdef DEBUG
  108.     (void) fprintf ( stderr, "UnFreeseCursor x = %d y = %d\n",
  109.         text -> x_pos, text -> y_pos);
  110. #endif DEBUG
  111.     if ( text -> cursor_stat != FREESE )
  112.         return;
  113.  
  114.     XDrawRectangle ( dpy, text -> window, text -> Igc,
  115.         text -> x_pos, text -> y_pos,
  116.         text -> cursor_width, text -> font_height );
  117.     text -> cursor_stat = OFF;
  118. }
  119.  
  120.  
  121.  
  122. /*
  123. **    Function name : TextCursorOff
  124. **
  125. **    Description : Eteint le curseur.
  126. **    Input : Le text courant.
  127. **    Ouput :
  128. */
  129. void TextCursorOff ( text )
  130.     Text    *text;
  131. {
  132.     if ( text -> cursor_stat == OFF )
  133.         return;
  134.  
  135.     if ( text -> cursor_stat == FREESE ) {
  136.         UnFreeseTextCursor ( text );
  137.         return;
  138.     }
  139. #ifdef DEBUG
  140.     (void) fprintf ( stderr, "Cursor Off x = %d y = %d\n",
  141.         text  -> x_pos, text -> y_pos);
  142. #endif DEBUG
  143.     XFillRectangle ( dpy, text -> window,text -> Igc,
  144.         text -> x_pos, text -> y_pos, text -> cursor_width,
  145.         text -> font_height );
  146.     text -> cursor_stat = OFF;
  147. }
  148.  
  149.  
  150. /*
  151. **    Function name : MoveToXYinTextWindow
  152. **
  153. **    Description : Deplace le curseur a la position (x, y)
  154. **        dans la page courante.
  155. **
  156. **    Input : Le text courant, la nouvelle position.
  157. **    Ouput : 0 si Ok -1 sinon
  158. */
  159. int MoveToXYinTextWindow ( text, x, y )
  160.     Text *text;
  161.     register int x, y;
  162. {
  163.     register char *s, *sh;
  164.     register int i, cur_line, new_line, delta;
  165.     char *HscrollString ();
  166.     int len;
  167.  
  168.     x -= MARGE;
  169.     y -= MARGE;
  170.  
  171.     cur_line = text -> n1 + 1;
  172.     new_line = (y / text -> font_height) + 1;
  173.  
  174.     if ( new_line > text -> lines_in_page )
  175.         new_line = text -> lines_in_page;
  176.  
  177.     if ( (delta = new_line - cur_line) == 0 ) {  /* meme ligne */
  178.         s = GetCurrentLine ( text -> buf, &len );
  179.         if ( text -> sl )
  180.             sh = HscrollString ( s, text -> sl, text -> tab_width );
  181.         else
  182.             sh = s;
  183.         for ( i = 1; i < (len -(sh -s) + 1); i++ ) { 
  184.             if ( MyTextWidth ( text , sh, i ) > x ) 
  185.                 break;
  186.         }
  187.         i += (sh -s);
  188.         (void) MoveHole ( text -> buf, i - GetNcFromLeft ( text -> buf ) - 1 );
  189.         return 0;
  190.     }
  191.     if ( (delta + text -> no_current_line) > text -> lines_in_buf ) {
  192.         return -1;        
  193.     }
  194.     (void) MoveToLine ( text -> buf, delta); /* On va sur la bonne ligne */
  195.     text -> n1 += delta;
  196.     text -> n2 -= delta;
  197.     text -> no_current_line += delta;
  198.  
  199.     SetLinesTable ( text );
  200.     s = GetCurrentLine ( text -> buf, &len );
  201.     if ( text -> sl )
  202.         sh = HscrollString ( s, text -> sl, text -> tab_width );
  203.     else
  204.         sh = s;
  205.     for ( i = 1; i < (len -(sh-s)+1); i++ ) {
  206.         if ( MyTextWidth ( text, sh, i ) > x ) 
  207.             break;
  208.     }
  209.     i += (sh - s);
  210.     (void) MoveHole ( text -> buf, i - 1 );
  211.     return (0);
  212. }
  213.  
  214.  
  215. /*
  216. **    Function name : MoveToBline
  217. **
  218. **    Description : Deplace le curseur au debut de la ligne courante
  219. **    Input : Le text courant.
  220. **    Ouput :
  221. */
  222. void MoveToBline ( text )
  223.     Text *text;
  224. {
  225.     register int n;
  226.  
  227.     if ( text -> sl )
  228.         GotoLeft ( text );
  229.  
  230.     n = GetNcFromLeft ( text -> buf );
  231.     (void) MoveHole ( text -> buf, -n );
  232. }
  233.  
  234.  
  235. /*
  236. **    Function name : MoveToEline
  237. **
  238. **    Description : Deplace le curseur a la fin de la ligne courante.
  239. **
  240. **    Input : Le text courant.
  241. **    Ouput :
  242. */
  243. void MoveToEline ( text )
  244.     Text *text;
  245. {
  246.     register int n;
  247.  
  248.      n = GetNcFromRight ( text -> buf );
  249.     (void) MoveHole ( text -> buf, n );
  250. }
  251.  
  252.  
  253. /*
  254. **    Function name : UpCursor
  255. **
  256. **    Description : Deplace le curseur sur la ligne
  257. **        precedente.
  258. **    Input : Le text courant.
  259. **    Ouput :
  260. */
  261. void UpCursor ( text )
  262.     Text *text;
  263. {
  264. #ifdef DEBUG
  265.        (void) fprintf ( stderr, "Up cursor\n" );
  266. #endif DEBUG
  267.  
  268.        if ( text -> no_current_line == 1 ) {
  269.           klaxon ();
  270.               return;
  271.        }
  272.  
  273.        if ( text -> n1 == NULL )                /* il faut scroller */
  274.          CurrentLineToMiddle ( text );
  275.  
  276.        (void) MoveToXYinTextWindow ( text, text -> x_pos,
  277.         text -> n1 * text -> font_height );
  278. }
  279.  
  280.  
  281. /*
  282. **    Function name : DownCursor
  283. **
  284. **    Description : Delace le curseur sur la ligne suivante.
  285. **    Input : Le text courant.
  286. **    Ouput :
  287. */
  288. void DownCursor ( text )
  289.     Text *text;
  290. {
  291.        register int y;
  292.  
  293. #ifdef DEBUG
  294.        (void) fprintf ( stderr, "Down cursor\n" );
  295. #endif DEBUG
  296.  
  297.        if ( text -> no_current_line >= text -> lines_in_buf ) {
  298.           klaxon ();
  299.               return;
  300.        }
  301.  
  302.        if ( text -> n2 == NULL ) {
  303.           CurrentLineToMiddle ( text );
  304.  
  305.           y = text -> y_pos -
  306.         (text -> n1 -1 ) * text -> font_height ;
  307.        }
  308.        else
  309.               y = text -> y_pos + text -> font_height;
  310.  
  311.        (void) MoveToXYinTextWindow ( text, text -> x_pos, y );
  312. }
  313.  
  314.  
  315. /*
  316. **    Function name : ForwardChar
  317. **
  318. **    Description : Deplace le curseur de 1 caractere vers la droite.
  319. **    Input : Le text courant.
  320. **    Ouput : True si Ok, False si fin de buffer.
  321. */
  322. int ForwardChar ( text )
  323.     Text *text;
  324. {
  325.        char c;
  326. #ifdef DEBUG
  327.        (void) fprintf ( stderr, "Forward char\n" );
  328. #endif DEBUG
  329.        GetCurrentChar ( text -> buf, &c );
  330.        if ( c == '\n' ) {
  331.           if ( text -> no_current_line > text -> lines_in_buf )
  332.              return False;
  333.           text -> no_current_line ++;
  334.           (void) MoveToLine ( text -> buf, 1 );
  335.           if ( text -> n2 == NULL ) {
  336.              CurrentLineToMiddle ( text );
  337.           }
  338.           else {
  339.                  text -> n1 ++;
  340.              text -> n2 --;
  341.           }
  342.        }
  343.        else if ( c == '\0' ) {
  344. #ifdef DEBUG
  345.           (void) fprintf ( stderr, " Fin du buffer\n" );
  346. #endif DEBUG
  347.           klaxon ();
  348.           return False;
  349.        }
  350.        else 
  351.           (void) MoveHole ( text -> buf, 1 );
  352.        return True;
  353. }
  354.  
  355.  
  356. /*
  357. **    Function name : BackwardChar
  358. **
  359. **    Description : Delplace le curseur de 1 caractere vers la gauche.
  360. **    Input : Le text courant.
  361. **    Ouput :
  362. */
  363. void BackwardChar ( text )
  364. Text *text;
  365. {
  366.        char c;
  367. #ifdef DEBUG
  368.        (void) fprintf ( stderr, "Backward char\n" );
  369. #endif DEBUG
  370.        if ( MoveHole ( text -> buf, -1 ) < NULL ) {
  371.           klaxon ();
  372.               return;
  373.        }
  374.        GetCurrentChar ( text -> buf, &c );
  375.        if ( c == '\n' ) {
  376.           text -> no_current_line --;
  377.           if ( text -> n1 == NULL )
  378.              CurrentLineToMiddle ( text );
  379.           else {
  380.                  text -> n1 --;
  381.              text -> n2 ++;
  382.           }
  383.        }
  384. }
  385.  
  386.  
  387. /*
  388. **    Function name : GetCurrentXY
  389. **
  390. **    Description : Retourne la position courante dans la page,
  391. **        (x, y) ainsi que le caractere courant.
  392. **    Input : Le text courant, la position et la caractere.
  393. **    Ouput :
  394. */
  395. static void GetCurrentXY ( text, x, y, c )
  396.     Text *text;
  397.     int *x, *y;     /* RETURN */
  398.     char *c;    /* RETURN */
  399. {
  400.     register char *s;  /* Current line */
  401.     register char *cl; /* Current line from left */
  402.     register int n, n0;
  403.     int len, clipx;
  404.     char *HscrollString ();
  405.  
  406.     if ( TextInBuf ( text ) == False ) {
  407.         *x = *y = MARGE;
  408.         *c = 0;
  409.         return;
  410.     }
  411.  
  412.     clipx = text -> width - ( 2 * MARGE );
  413.     cl = GetCurrentLine ( text -> buf, &len );
  414.  
  415.     if ( text -> page.sline [ text -> n1 + 1 ] == 0 )
  416.         (void) fprintf ( stderr, "Warning page.sline 0\n" );
  417.  
  418.     if ( text -> sl )
  419.         s = HscrollString ( cl, text -> sl, text -> tab_width );
  420.     else
  421.         s = cl;
  422.  
  423.     if ( s == 0 ) 
  424.         (void) fprintf ( stderr, "Internal Error 2...\n" );
  425.  
  426.     *y = MARGE + ( text -> n1 * text -> font_height );
  427.     n0 = GetNcFromLeft ( text -> buf );
  428.     n = n0 - ( s - cl );
  429.  
  430.     if ( (n <= 0) && (text -> sl) ) {
  431.         do {
  432.             text -> sl --;
  433.             SetLinesTable ( text );
  434.             s = text -> page.sline [ text -> n1 + 1 ];
  435.             *x = MARGE + MyTextWidth ( text, s, n );
  436.             n = n0 - ( s - cl );
  437.         } while ( (n <= 0) && (text -> sl));
  438.            
  439.         ClipOn ( text, NULL );
  440.         ClearPage ( text );
  441.         RefreshPage ( text );
  442.         ClipOff ( text );
  443.     }
  444.  
  445.     if ( ( *x = MARGE + MyTextWidth ( text, s, n )) > clipx ) {
  446.         do {
  447.             text -> sl ++;
  448.             SetLinesTable ( text );
  449.             s = text -> page.sline [ text -> n1 + 1 ];
  450.             n = n0 - ( s - cl );
  451.         } while ( ( *x = MARGE + MyTextWidth ( text, s, n )) > clipx );
  452.  
  453.         ClipOn ( text, NULL );
  454.         ClearPage ( text );
  455.         RefreshPage ( text );
  456.         ClipOff ( text );
  457.     } 
  458.  
  459.     if ( text -> no_current_line > text -> lines_in_buf )
  460.         *x = MARGE;
  461.  
  462.     (void) strncpy ( c,(char *) (s+n), 1 );
  463. #ifdef DEBUG
  464.     (void) fprintf ( stderr, "n = %d x = %d c = %c\n", n, *x, *c );
  465. #endif
  466. }
  467.  
  468.  
  469. /*
  470. **    Function name : MyTextWidth
  471. **
  472. **    Description : Retourne la longueur en pixel des i premiers
  473. **        caracteres de la chaine s.
  474. **        Cette fonction tient compte des tabs.
  475. **    Input : Le text courant, la chaine, nb caracteres.
  476. **    Ouput : La longueur en pixel.
  477. */
  478. static int MyTextWidth ( text, str, i )
  479.     Text *text;
  480.     register char *str;
  481.     register int i;
  482. {
  483.         register char *p, *s;
  484.     register int n = 1; /* Caractere en cours de traitement */
  485.     register int xx, x, width;
  486.     register int sizetab = text -> tab_width * text -> char_width_ave;
  487.  
  488.     xx = x = width = 0;
  489.     p = s = str;
  490.  
  491.     if ( str == NULL ) 
  492.             (void) fprintf ( stderr, "Internal Error 3...\n" );
  493.  
  494.     while ( *p != '\n' ) {
  495.             if ( (*p == NULL) || (i == 0) )
  496.                 break;
  497.         if ( *p == '\t' ) {
  498.             xx =  sizetab;
  499.             width = XTextWidth ( text -> font, s, n - 1); 
  500.             while ( width >= xx )     
  501.                     xx += sizetab;
  502.             x += xx;
  503.             s = ++p;
  504.             n = 1;
  505.         }
  506.         else {
  507.                 n++;
  508.             p++;
  509.         }
  510.         i--;
  511.     }
  512.     return ( x + XTextWidth ( text -> font, s, n - 1 ));
  513. }
  514.  
  515.  
  516. /*
  517. **    Function name : HscrollString
  518. **
  519. **    Description : Calcul du scroll horizontal.
  520. **    Input : La chaine, le nb de tabulation et la taille de celle-ci
  521. **    Ouput : Le premier caractere de la chaine corrspondant
  522. **        a la tabulation souhaitee.
  523. */
  524. char *HscrollString ( s, n, tabwidth )
  525.     register char *s;
  526.     register int n, tabwidth;
  527. {
  528.     register int d = n * tabwidth; 
  529.  
  530.     while ( d > NULL ) {
  531.         if ( *s == '\0' )
  532.             return 0;
  533.         if ( *s == '\n' )
  534.             break;
  535.         if ( *s == '\t' ) {
  536.             d -= tabwidth;
  537.             s++;
  538.             continue;
  539.         }
  540.         s++;
  541.         d--;
  542.     }
  543.     return s;
  544. }
  545.  
  546.  
  547. /*
  548. **    Function name : GotoLeft
  549. **
  550. **    Description : Met le scroll horizontal a zero.
  551. **    Input : Le text courant.
  552. **    Ouput :
  553. */
  554. void GotoLeft ( text )
  555. Text *text;
  556. {
  557.         text -> sl = 0;
  558.     ClearPage ( text );
  559.     SetAndDisplayPage ( text );
  560.     DisplayMessage ( text -> mwin, " " );
  561.     MCLEAR ( text -> stat, MESSAGE);
  562. }
  563.  
  564.