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.
 
 
 
 

469 lines
13 KiB

  1. /* Copyright (C) 2011-2014 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. int nc;
  141. for (iTERM=0; iTERM<3; iTERM++) {
  142. if (tcgetattr(iTERM, &t0) != -1) break;
  143. if (iTERM<2) continue;
  144. perror("No terminal found ! tcgetattr"); /* sauvegarde */
  145. exit(2);
  146. }
  147. if (tcgetattr(iTERM, &t1) == -1) perror("tcgetattr");
  148. /* cfmakeraw(&t1); */
  149. t1.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
  150. | INLCR | IGNCR | ICRNL | IXON);
  151. /* t1.c_oflag &= ~OPOST; */
  152. /* t1.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); */
  153. t1.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
  154. t1.c_cflag &= ~(CSIZE | PARENB);
  155. t1.c_cflag |= CS8;
  156. if (tcsetattr(iTERM, TCSAFLUSH, &t1) == -1) perror("tcsetattr"); /* raw */
  157. /* clear screen */
  158. nc=system("clear");
  159. }
  160. void termReset(void)
  161. {
  162. if (tcsetattr(iTERM, TCSAFLUSH, &t0) == -1) perror("tcsetattr");/*restaure*/
  163. }
  164. void enleve1(char * s)
  165. {
  166. char * w;
  167. w=s;
  168. while (*w != '\0') *w++ = *(w+1);
  169. }
  170. void insertC(char c, char * s)
  171. {
  172. char *w;
  173. w=s;
  174. while (*w != '\0') w++;
  175. while (w >= s) { *(w+1) = *w; w--; }
  176. *s=c;
  177. }
  178. int lireLigne(int fd, char *b, char *s, int nc)
  179. /* fd = file descriptor
  180. b = adresse du buffer
  181. nc = nb de caracteres possible (longueur du buffer */
  182. {
  183. char *d, *f, c, c2, c3, *h, *w, *Wl, *rac;
  184. int n, i, l, ls=0, ins=0, ignTild=0, nbT=0, Nc;
  185. unsigned int j;
  186. /* printf("lireLigne ... \n"); */
  187. d = b;
  188. f = b+nc;
  189. while(d<f-ls) {
  190. if (noErr()) {
  191. n = -1;
  192. break;
  193. }
  194. /* fprintf(stderr,"d-b=%d ins=%d s=<%s> b=<%s>\n",d-b,ins,s,b); */
  195. if ((n=read(fd,d,1)) != 1) break;
  196. c=*d;
  197. if (ignTild && (c == '~')) {
  198. ignTild=0; continue;
  199. }
  200. if ((c > 31) && (c < 127)) { /* de SPACE a TILDE */
  201. if (!((FD_IN || iTERM) && ECHOOFF)) {
  202. printf("%c",c);
  203. if (ins) {
  204. if (ins==2) /* rewrite */
  205. enleve1(s);
  206. if(*s =='\0') ins=0;
  207. else {
  208. printf("%s",s);
  209. for (j=0; j<strlen(s); j++) printf("\b");
  210. }
  211. }
  212. }
  213. fflush(stdout);
  214. d++;
  215. } else {
  216. switch (c) {
  217. /* Ctrl C
  218. case '\003' :
  219. kill(getpid(), SIGINT);
  220. break; */
  221. case '\t': /* tab */
  222. if (d>b) {
  223. *d='\0';
  224. w=d-1;
  225. while ((w>b) && (!(isSepa(*w,1)))) w--;
  226. if (isSepa(*w,0)) w++;
  227. /* fprintf(stderr,"d-b=%d w=<%s>\n",d-b,w); */
  228. if (strlen(w) > 0) {
  229. j=nbLibBegin(w, &rac);
  230. /* fprintf(stderr,"j=%d w=<%s>\n",j,w); */
  231. if (j==0) printf("\a");
  232. else {
  233. if (j==1) {
  234. Wl=getLibBegin(w);
  235. i=strlen(Wl)-strlen(w);
  236. /* fprintf(stderr,"i=%d Wl=<%s>\n",i,Wl); */
  237. if (i>0) {
  238. strcpy(w,Wl);
  239. printf("%s ",d);
  240. d+=i;
  241. *d++ = ' ';
  242. if (ins) {
  243. printf("%s ",s);
  244. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  245. }
  246. } else { /* XXXX */
  247. if (i==0) {
  248. printf (" ");
  249. *d++ = ' ';
  250. }
  251. }
  252. } else {
  253. if (rac != NULL) {
  254. i=strlen(rac)-strlen(w);
  255. strcpy(w,rac);
  256. printf("%s",d);
  257. d+=i;
  258. if (ins) {
  259. printf("%s ",s);
  260. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  261. }
  262. } else {
  263. nbT++;
  264. if (nbT>1) {
  265. nbT=0;
  266. printf("\n");
  267. listLibBegin(w);
  268. *d='\0';
  269. printf("> %s",b);
  270. if (ins) {
  271. printf("%s ",s);
  272. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  273. }
  274. fflush(stdout);
  275. }
  276. }
  277. }
  278. }
  279. fflush(stdout);
  280. }
  281. }
  282. break;
  283. case '\177':
  284. if (d>b) {
  285. printf("\b \b");
  286. if (ins) {
  287. printf("%s ",s);
  288. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  289. }
  290. fflush(stdout);
  291. d--;
  292. }
  293. break;
  294. case '\n':
  295. case '\r':
  296. if ((FD_IN || iTERM) && ECHOOFF) printf(".");
  297. else {
  298. printf("\n");
  299. if (ins) {
  300. if (d+strlen(s) < f) {
  301. sprintf(d,"%s",s);
  302. d+=strlen(s);
  303. } else return(-1);
  304. }
  305. }
  306. goto finBoucle;
  307. /* gestion des caracteres speciaux */
  308. case '\033': /* ESCAPE */
  309. ignTild=1;
  310. Nc=read(fd,&c2,1);
  311. Nc=read(fd,&c3,1);
  312. if (c2 == '[') {
  313. switch(c3) {
  314. case '2' : /* Insert */
  315. if (ins) {
  316. ins++;
  317. if (ins==3) ins=1;
  318. }
  319. break;
  320. case '3' : /* Suppr */
  321. if (ins) {
  322. enleve1(s);
  323. if(*s =='\0') ins=0;
  324. printf("%s \b",s);
  325. for (j=0; j<strlen(s); j++) printf("\b");
  326. fflush(stdout);
  327. }
  328. break;
  329. case 'A' :
  330. case 'B' :
  331. ins = 0;
  332. /* efface la ligne en cours */
  333. l=d-b;
  334. for(i=0;i<l;i++) printf("\b \b");
  335. fflush(stdout);
  336. d=b;
  337. *d = '\0';
  338. if ((h=getHisto(c3)) != NULL) {
  339. strcpy(b,h);
  340. d=b+strlen(h);
  341. /*
  342. printf("\n%s (iH=%d iHt=%d)\n",h,iH,iHt);
  343. *d='\0';
  344. */
  345. printf("%s",b);
  346. fflush(stdout);
  347. }
  348. break;
  349. case 'C' : /* -> */
  350. if (ins) {
  351. *d = *s;
  352. printf("%c",*d++);
  353. enleve1(s);
  354. if(*s =='\0') ins=0;
  355. else {
  356. printf("%s",s);
  357. for (j=0; j<strlen(s); j++) printf("\b");
  358. }
  359. fflush(stdout);
  360. }
  361. break;
  362. case 'D' : /* <- */
  363. if (d>b) {
  364. if (ins==0) {
  365. ins=1;
  366. *d='\0';
  367. strcpy(s,d-1);
  368. } else insertC(*(d-1),s);
  369. d--;
  370. printf("\b");
  371. fflush(stdout);
  372. }
  373. break;
  374. default:
  375. printf("\nESC [ %d (%c) !\n",(int)c3, c3);
  376. *d='\0';
  377. printf("> %s",b);
  378. fflush(stdout);
  379. }
  380. } else {
  381. if (c2 == 'O') {
  382. switch(c3) {
  383. case 'P' : /* F1 */
  384. break;
  385. case 'Q' : /* F2 */
  386. break;
  387. case 'R' : /* F3 */
  388. break;
  389. case 'S' : /* F4 */
  390. break;
  391. }
  392. } else {
  393. printf("\nESC %d %d (%c) !\n",(int)c2,(int)c3, c3);
  394. *d='\0';
  395. printf("> %s",b);
  396. fflush(stdout);
  397. }
  398. }
  399. break;
  400. default :
  401. /*
  402. printf("\nCar = %d !\n",(int)c);
  403. *d='\0';
  404. printf("> %s",b);
  405. fflush(stdout);
  406. */
  407. break;
  408. }
  409. }
  410. if (ins) ls = strlen(s);
  411. }
  412. finBoucle:
  413. /* printf("fin lireLigne!\n"); */
  414. if ((n<1) && (FD_IN !=0)) {
  415. closeFD(); /* fichier loader */
  416. if (ECHOOFF) printf("\n");
  417. return 0;
  418. }
  419. if ((n<1) && iTERM) {
  420. close(FD_IN); /* pipe ou autre */
  421. Nc=dup(iTERM); /* stdin on term */
  422. iTERM = 0;
  423. if (ECHOOFF) printf("\n");
  424. return 0;
  425. }
  426. if (d == f) { /* cas du buffer trop petit */
  427. /* d=b;
  428. while (*d != '\n') read(fd,d,1);
  429. **** not in raw mode */
  430. #ifdef DEBUG
  431. printf("lireLigne : erreur !\n");
  432. #endif
  433. return(-1);
  434. }
  435. *d = '\0';
  436. #ifdef DEBUG
  437. printf("lireLigne : retour <%s> !\n",b);
  438. #endif
  439. if (!FD_IN) putHisto(b);
  440. incFDlig();
  441. return(strlen(b));
  442. }