Nife version Beta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

461 lines
13 KiB

  1. /* Copyright (C) 2011-2013 Patrick H. E. Foubet - S.E.R.I.A.N.E.
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or any
  5. later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>
  12. *******************************************************************/
  13. /* histo.c */
  14. #include "conf.h"
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <signal.h>
  19. #include <sys/types.h>
  20. #include <sys/wait.h>
  21. #include <sys/stat.h>
  22. #include <fcntl.h>
  23. #include <termios.h>
  24. #include <unistd.h>
  25. #include "histo.h"
  26. #include "nife.h"
  27. #include "mth.h"
  28. #include "err.h"
  29. #include "lib.h"
  30. #include "debug.h"
  31. #define HISTOMAX 100
  32. static char * HIST[HISTOMAX];
  33. static int iH=0, iHt, iHl, iHFull=0;
  34. #define FDMAX 128
  35. static int iFD=0;
  36. static int FD_T[FDMAX], FD_L[FDMAX]; /* fd table and line numbers */
  37. static void *FD_N[FDMAX];
  38. void IF_showFD(void)
  39. {
  40. printf("iFD=%d FD_T=%d FD_L=%d\n",iFD, FD_T[iFD], FD_L[iFD]);
  41. }
  42. void addFD(int fd, char*S)
  43. {
  44. void *M;
  45. iFD++;
  46. /* printf("addFD iFD=%d\n",iFD); */
  47. if (iFD == FDMAX) {
  48. iFD--;
  49. messErr(45);
  50. return;
  51. }
  52. _MODIF_FD_IN_(fd);
  53. FD_T[iFD]=fd;
  54. FD_L[iFD]=0;
  55. if ((M = malloc(strlen(S)+1)) == NULL) stopErr("addFD","malloc");
  56. #ifdef DEBUG_M
  57. printf("New String address : %lu \n",(unsigned long)M);
  58. #endif
  59. strcpy((char*)M,S);
  60. FD_N[iFD]=M;
  61. }
  62. void closeFD(void)
  63. {
  64. /* printf("closeFD iFD=%d\n",iFD); */
  65. close(FD_IN);
  66. free(FD_N[iFD]);
  67. iFD--;
  68. if (iFD) _MODIF_FD_IN_(FD_T[iFD]);
  69. else _MODIF_FD_IN_(0);
  70. }
  71. int getFDlig(void)
  72. {
  73. return FD_L[iFD];
  74. }
  75. char * getFDname(void)
  76. {
  77. return (char*)FD_N[iFD];
  78. }
  79. void incFDlig(void)
  80. {
  81. FD_L[iFD]++;
  82. }
  83. void razHisto(void)
  84. {
  85. int i;
  86. for(i=0;i<iH;i++) free((void*)HIST[i]);
  87. iH=0;
  88. }
  89. void putHisto(char *C)
  90. {
  91. int L;
  92. if ((L=strlen(C)) == 0) return;
  93. HIST[iH] = (char*)malloc(L+1);
  94. if (HIST[iH] != NULL) {
  95. strcpy(HIST[iH],C);
  96. iHt=iH; /* depart recherche */
  97. iH++;
  98. iHl=iH;
  99. if (iH == HISTOMAX) {
  100. iHFull=1;
  101. iH=0;
  102. }
  103. }
  104. }
  105. char * getHisto(char S) /* Sens A remonte, B descend */
  106. {
  107. char * C;
  108. if (S == 'B') {
  109. if (iHt == iH-1) {
  110. iHl=iH;
  111. printf("\a");
  112. fflush(stdout);
  113. C = NULL;
  114. } else {
  115. iHt++;
  116. if (iHt == HISTOMAX) iHt=0;
  117. if (iHl==iHt) iHt++;
  118. C = HIST[iHt];
  119. iHl=iHt;
  120. }
  121. } else { /* A */
  122. if (iHt == -1) {
  123. iHl=iHt;
  124. printf("\a");
  125. fflush(stdout);
  126. C = NULL;
  127. } else {
  128. if (iHl==iHt) iHt--;
  129. iHl=iHt;
  130. C = HIST[iHt--];
  131. if ((iHt < 0) && (iHFull)) iHt = HISTOMAX-1;
  132. }
  133. }
  134. return(C);
  135. }
  136. static struct termios t0, t1;
  137. int iTERM=0;
  138. void termInit(void)
  139. {
  140. for (iTERM=0; iTERM<3; iTERM++) {
  141. if (tcgetattr(iTERM, &t0) != -1) break;
  142. if (iTERM<2) continue;
  143. perror("No terminal found ! tcgetattr"); /* sauvegarde */
  144. exit(2);
  145. }
  146. if (tcgetattr(iTERM, &t1) == -1) perror("tcgetattr");
  147. /* cfmakeraw(&t1); */
  148. t1.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
  149. | INLCR | IGNCR | ICRNL | IXON);
  150. /* t1.c_oflag &= ~OPOST; */
  151. t1.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  152. t1.c_cflag &= ~(CSIZE | PARENB);
  153. t1.c_cflag |= CS8;
  154. if (tcsetattr(iTERM, TCSAFLUSH, &t1) == -1) perror("tcsetattr"); /* raw */
  155. }
  156. void termReset(void)
  157. {
  158. if (tcsetattr(iTERM, TCSAFLUSH, &t0) == -1) perror("tcsetattr");/*restaure*/
  159. }
  160. void enleve1(char * s)
  161. {
  162. char * w;
  163. w=s;
  164. while (*w != '\0') *w++ = *(w+1);
  165. }
  166. void insertC(char c, char * s)
  167. {
  168. char *w;
  169. w=s;
  170. while (*w != '\0') w++;
  171. while (w >= s) { *(w+1) = *w; w--; }
  172. *s=c;
  173. }
  174. int lireLigne(int fd, char *b, char *s, int nc)
  175. /* fd = file descriptor
  176. b = adresse du buffer
  177. nc = nb de caracteres possible (longueur du buffer */
  178. {
  179. char *d, *f, c, c2, c3, *h, *w, *Wl, *rac;
  180. int n, i, l, ls=0, ins=0, ignTild=0, nbT=0;
  181. unsigned int j;
  182. /* printf("lireLigne ... \n"); */
  183. d = b;
  184. f = b+nc;
  185. while(d<f-ls) {
  186. if (noErr()) {
  187. n = -1;
  188. break;
  189. }
  190. /* fprintf(stderr,"d-b=%d ins=%d s=<%s> b=<%s>\n",d-b,ins,s,b); */
  191. if ((n=read(fd,d,1)) != 1) break;
  192. c=*d;
  193. if (ignTild && (c == '~')) {
  194. ignTild=0; continue;
  195. }
  196. if ((c > 31) && (c < 127)) { /* de SPACE a TILDE */
  197. if (!((FD_IN || iTERM) && ECHOOFF)) {
  198. printf("%c",c);
  199. if (ins) {
  200. if (ins==2) /* rewrite */
  201. enleve1(s);
  202. if(*s =='\0') ins=0;
  203. else {
  204. printf("%s",s);
  205. for (j=0; j<strlen(s); j++) printf("\b");
  206. }
  207. }
  208. }
  209. fflush(stdout);
  210. d++;
  211. } else {
  212. switch (c) {
  213. case '\t': /* tab */
  214. if (d>b) {
  215. *d='\0';
  216. w=d-1;
  217. while ((w>b) && (!(isSepa(*w,1)))) w--;
  218. if (isSepa(*w,0)) w++;
  219. /* fprintf(stderr,"d-b=%d w=<%s>\n",d-b,w); */
  220. if (strlen(w) > 0) {
  221. j=nbLibBegin(w, &rac);
  222. /* fprintf(stderr,"j=%d w=<%s>\n",j,w); */
  223. if (j==0) printf("\a");
  224. else {
  225. if (j==1) {
  226. Wl=getLibBegin(w);
  227. i=strlen(Wl)-strlen(w);
  228. /* fprintf(stderr,"i=%d Wl=<%s>\n",i,Wl); */
  229. if (i>0) {
  230. strcpy(w,Wl);
  231. printf("%s ",d);
  232. d+=i;
  233. *d++ = ' ';
  234. if (ins) {
  235. printf("%s ",s);
  236. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  237. }
  238. } else { /* XXXX */
  239. if (i==0) {
  240. printf (" ");
  241. *d++ = ' ';
  242. }
  243. }
  244. } else {
  245. if (rac != NULL) {
  246. i=strlen(rac)-strlen(w);
  247. strcpy(w,rac);
  248. printf("%s",d);
  249. d+=i;
  250. if (ins) {
  251. printf("%s ",s);
  252. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  253. }
  254. } else {
  255. nbT++;
  256. if (nbT>1) {
  257. nbT=0;
  258. printf("\n");
  259. listLibBegin(w);
  260. *d='\0';
  261. printf("> %s",b);
  262. if (ins) {
  263. printf("%s ",s);
  264. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  265. }
  266. fflush(stdout);
  267. }
  268. }
  269. }
  270. }
  271. fflush(stdout);
  272. }
  273. }
  274. break;
  275. case '\177':
  276. if (d>b) {
  277. printf("\b \b");
  278. if (ins) {
  279. printf("%s ",s);
  280. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  281. }
  282. fflush(stdout);
  283. d--;
  284. }
  285. break;
  286. case '\n':
  287. case '\r':
  288. if ((FD_IN || iTERM) && ECHOOFF) printf(".");
  289. else {
  290. printf("\n");
  291. if (ins) {
  292. if (d+strlen(s) < f) {
  293. sprintf(d,"%s",s);
  294. d+=strlen(s);
  295. } else return(-1);
  296. }
  297. }
  298. goto finBoucle;
  299. /* gestion des caracteres speciaux */
  300. case '\033': /* ESCAPE */
  301. ignTild=1;
  302. read(fd,&c2,1);
  303. read(fd,&c3,1);
  304. if (c2 == '[') {
  305. switch(c3) {
  306. case '2' : /* Insert */
  307. if (ins) {
  308. ins++;
  309. if (ins==3) ins=1;
  310. }
  311. break;
  312. case '3' : /* Suppr */
  313. if (ins) {
  314. enleve1(s);
  315. if(*s =='\0') ins=0;
  316. printf("%s \b",s);
  317. for (j=0; j<strlen(s); j++) printf("\b");
  318. fflush(stdout);
  319. }
  320. break;
  321. case 'A' :
  322. case 'B' :
  323. ins = 0;
  324. /* efface la ligne en cours */
  325. l=d-b;
  326. for(i=0;i<l;i++) printf("\b \b");
  327. fflush(stdout);
  328. d=b;
  329. *d = '\0';
  330. if ((h=getHisto(c3)) != NULL) {
  331. strcpy(b,h);
  332. d=b+strlen(h);
  333. /*
  334. printf("\n%s (iH=%d iHt=%d)\n",h,iH,iHt);
  335. *d='\0';
  336. */
  337. printf("%s",b);
  338. fflush(stdout);
  339. }
  340. break;
  341. case 'C' : /* -> */
  342. if (ins) {
  343. *d = *s;
  344. printf("%c",*d++);
  345. enleve1(s);
  346. if(*s =='\0') ins=0;
  347. else {
  348. printf("%s",s);
  349. for (j=0; j<strlen(s); j++) printf("\b");
  350. }
  351. fflush(stdout);
  352. }
  353. break;
  354. case 'D' : /* <- */
  355. if (d>b) {
  356. if (ins==0) {
  357. ins=1;
  358. *d='\0';
  359. strcpy(s,d-1);
  360. } else insertC(*(d-1),s);
  361. d--;
  362. printf("\b");
  363. fflush(stdout);
  364. }
  365. break;
  366. default:
  367. printf("\nESC [ %d (%c) !\n",(int)c3, c3);
  368. *d='\0';
  369. printf("> %s",b);
  370. fflush(stdout);
  371. }
  372. } else {
  373. if (c2 == 'O') {
  374. switch(c3) {
  375. case 'P' : /* F1 */
  376. break;
  377. case 'Q' : /* F2 */
  378. break;
  379. case 'R' : /* F3 */
  380. break;
  381. case 'S' : /* F4 */
  382. break;
  383. }
  384. } else {
  385. printf("\nESC %d %d (%c) !\n",(int)c2,(int)c3, c3);
  386. *d='\0';
  387. printf("> %s",b);
  388. fflush(stdout);
  389. }
  390. }
  391. break;
  392. default :
  393. /*
  394. printf("\nCar = %d !\n",(int)c);
  395. *d='\0';
  396. printf("> %s",b);
  397. fflush(stdout);
  398. */
  399. break;
  400. }
  401. }
  402. if (ins) ls = strlen(s);
  403. }
  404. finBoucle:
  405. /* printf("fin lireLigne!\n"); */
  406. if ((n<1) && (FD_IN !=0)) {
  407. closeFD(); /* fichier loader */
  408. if (ECHOOFF) printf("\n");
  409. return 0;
  410. }
  411. if ((n<1) && iTERM) {
  412. close(FD_IN); /* pipe ou autre */
  413. dup(iTERM); /* stdin on term */
  414. iTERM = 0;
  415. if (ECHOOFF) printf("\n");
  416. return 0;
  417. }
  418. if (d == f) { /* cas du buffer trop petit */
  419. /* d=b;
  420. while (*d != '\n') read(fd,d,1);
  421. **** not in raw mode */
  422. #ifdef DEBUG
  423. printf("lireLigne : erreur !\n");
  424. #endif
  425. return(-1);
  426. }
  427. *d = '\0';
  428. #ifdef DEBUG
  429. printf("lireLigne : retour <%s> !\n",b);
  430. #endif
  431. if (!FD_IN) putHisto(b);
  432. incFDlig();
  433. return(strlen(b));
  434. }