sysxwin.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046
  1. /* sysxwin.c Copyright (C) 1993-6 Codemist Ltd */
  2. /*
  3. * General Unix/X/StdWin system-specific code
  4. */
  5. /* Signature: 1e68f6c9 07-Mar-2000 */
  6. #include "machine.h"
  7. #ifndef NO_UNISTD_AVAILABLE
  8. /*
  9. * Posix mandates a header <unistd.h>, which is why I feel entitled to
  10. * include it here. But for systems that do not I can assert
  11. * NO_UNISTD_AVAILABLE in machine.h and worry about other ways to
  12. * reference the relevant facilities...
  13. */
  14. #include <unistd.h>
  15. #endif
  16. #ifdef __hpux
  17. /*
  18. * Get the regular headers to define a few more things...
  19. */
  20. #define _SYSCALL_INCLUDED
  21. #endif
  22. #include <stdarg.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <dirent.h>
  29. #include <errno.h>
  30. #include "tags.h"
  31. #include "externs.h"
  32. #include "sys.h"
  33. #ifdef TIMEOUT
  34. #include "timeout.h"
  35. #endif
  36. #include "filename.c"
  37. int change_directory(char *filename, char *old, size_t n)
  38. {
  39. process_file_name(filename, old, n);
  40. if (*filename == 0) return 1;
  41. if (chdir(filename))
  42. { char err_buf[LONGEST_LEGAL_FILENAME+100];
  43. char *msg;
  44. switch (errno)
  45. {
  46. case ENOTDIR:
  47. msg = "A component of %s is not a directory.";
  48. break;
  49. case ENOENT:
  50. msg = "The directory %s does not exist.";
  51. break;
  52. case EACCES:
  53. msg = "Insufficient permission for %s.";
  54. break;
  55. case ELOOP:
  56. msg = "Pathname %s has too many symbolic links.";
  57. break;
  58. case ENAMETOOLONG:
  59. msg = "The pathname %s is too long.";
  60. break;
  61. default:
  62. msg = "Cannot change directory to %s.";
  63. break;
  64. }
  65. sprintf(err_buf, msg, filename);
  66. aerror0(err_buf);
  67. return 1;
  68. }
  69. else return 0;
  70. }
  71. int create_directory(char *filename, char *old, size_t n)
  72. {
  73. process_file_name(filename, old, n);
  74. if (*filename == 0) return 1;
  75. return mkdir(filename, 0x1f8);
  76. }
  77. static void remove_files(char *name, int dirp, long int size)
  78. /* Remove a file, or a directory and all its contents */
  79. {
  80. if (dirp)
  81. rmdir(name);
  82. else
  83. remove(name);
  84. }
  85. int delete_file(char *filename, char *old, size_t n)
  86. {
  87. process_file_name(filename, old, n);
  88. if (*filename == 0) return 0;
  89. /*
  90. * We cannot simply use remove here, since this will not
  91. * work with directories and their contents. Hence the
  92. * use of scan_directory.
  93. */
  94. scan_directory(filename, remove_files);
  95. return 0;
  96. }
  97. /*#include <direct.h> */
  98. int get_current_directory(char *s, int n)
  99. {
  100. if (getcwd(s, n) == 0)
  101. { switch(errno)
  102. {
  103. case ERANGE:
  104. aerror0("the pathname of the current directory is too long.");
  105. break;
  106. case EACCES:
  107. aerror0("insufficient permission to get pathname.");
  108. break;
  109. default:
  110. aerror0("cannot get current directory name.");
  111. break;
  112. }
  113. *s = 0;
  114. return 0;
  115. }
  116. else return strlen(s);
  117. }
  118. int directoryp(char *filename, char *old, size_t n)
  119. {
  120. struct stat buf;
  121. process_file_name(filename, old, n);
  122. if (*filename == 0) return 0;
  123. if (stat(filename,&buf) == -1) return 0;
  124. return ((buf.st_mode & S_IFMT) == S_IFDIR);
  125. }
  126. char *get_truename(char *filename, char *old, size_t n)
  127. {
  128. struct stat buf;
  129. char *temp, *fn, *dir, *pwd;
  130. process_file_name(filename, old, n);
  131. if (*filename == 0) aerror("truename");
  132. /* Find out whether we have a file or a directory */
  133. if (stat(filename,&buf) == -1) aerror0("truename: cannot stat file");
  134. /* Store current directory */
  135. /* /*
  136. * The next line is UNSATISFACTORY because Posix explicitly says (at least in
  137. * in the copy of 1003.1 that I have) that getcwd has undefined behaviour
  138. * if its first argument is NULL.
  139. */
  140. if ((pwd = (char *)getcwd((char *)NULL, LONGEST_LEGAL_FILENAME)) == NULL)
  141. aerror0("truename: cannot get current working directory");
  142. if ((buf.st_mode & S_IFMT) == S_IFDIR)
  143. { /* We have a directory */
  144. char *dir = (char*) malloc(LONGEST_LEGAL_FILENAME);
  145. if (chdir(filename) != 0)
  146. aerror0("truename: cannot change directory");
  147. if (getcwd(dir,LONGEST_LEGAL_FILENAME) == NULL)
  148. aerror0("truename: cannot get current working directory");
  149. if (chdir(pwd) != 0)
  150. aerror0("truename: cannot change directory");
  151. free(pwd);
  152. /*
  153. * Axiom-specific hack: truename preserves '/' at the end of
  154. * a path
  155. */
  156. if (old[n-1] == '/' && dir[strlen(dir)-1] != '/')
  157. { n = strlen(dir);
  158. dir[n] = '/';
  159. dir[n+1] = '\0';
  160. }
  161. return dir;
  162. }
  163. else
  164. { /* Assume we have some kind of file */
  165. temp = strrchr(filename,'/');
  166. if (temp)
  167. { /* Found a directory component */
  168. fn = strdup(temp);
  169. *temp = '\0';
  170. /* fn is now "/file" and filename is the directory */
  171. if (chdir(filename) != 0)
  172. aerror0("truename: cannot change directory");
  173. /* /* getcwd(NULL,...) invalid */
  174. if ((temp = (char *)getcwd((char *)NULL,LONGEST_LEGAL_FILENAME)) == NULL)
  175. aerror0("truename: cannot get current working directory");
  176. if (chdir(pwd) != 0)
  177. aerror0("truename: cannot change directory");
  178. dir = (char *)malloc((strlen(temp) + strlen(fn) + 1)*sizeof(char));
  179. /* /*
  180. * No check for malloc failure...
  181. */
  182. strcpy(dir, temp);
  183. free(temp);
  184. free(pwd);
  185. strcat(dir, fn);
  186. free(fn);
  187. return dir;
  188. }
  189. else
  190. { dir = (char *)malloc((strlen(pwd) + strlen(filename) + 2)*sizeof(char));
  191. /* /* No check for malloc failure */
  192. strcpy(dir,pwd);
  193. strcat(dir, "/");
  194. strcat(dir, filename);
  195. free(pwd);
  196. return dir;
  197. }
  198. }
  199. }
  200. #ifndef DO_NOT_USE_STAT
  201. int file_readable(char *filename, char *old, size_t n)
  202. {
  203. struct stat buf;
  204. process_file_name(filename, old, n);
  205. if (*filename == 0) return 0;
  206. if (stat(filename,&buf) == -1)
  207. return 0; /* File probably does not exist */
  208. else if (geteuid() == buf.st_uid)
  209. return (buf.st_mode & S_IRUSR);
  210. else if (getegid() == buf.st_gid)
  211. return (buf.st_mode & S_IRGRP);
  212. else
  213. return (buf.st_mode & S_IROTH);
  214. }
  215. int file_writeable(char *filename, char *old, size_t n)
  216. {
  217. struct stat buf;
  218. process_file_name(filename, old, n);
  219. if (*filename == 0) return 0;
  220. if (stat(filename,&buf) == -1)
  221. return 0; /* Should we check to see if the directory is writeable? */
  222. else if (geteuid() == buf.st_uid)
  223. return (buf.st_mode & S_IWUSR);
  224. else if (getegid() == buf.st_gid)
  225. return (buf.st_mode & S_IWGRP);
  226. else
  227. return (buf.st_mode & S_IWOTH);
  228. }
  229. #else
  230. int file_readable(char *filename, char *old, size_t n)
  231. {
  232. FILE *fp;
  233. process_file_name(filename, old, n);
  234. if (*filename == 0) return 0;
  235. /* The "correct" way to do this is via stat, but this is much simpler! */
  236. fp = fopen(filename,"r");
  237. if (fp == NULL) return 0;
  238. else
  239. { fclose(fp);
  240. return 1;
  241. }
  242. }
  243. int file_writeable(char *filename, char *old, size_t n)
  244. {
  245. FILE *fp;
  246. process_file_name(filename, old, n);
  247. if (*filename == 0) return 0;
  248. fp = fopen(filename,"a");
  249. if (fp == NULL) return 0;
  250. else
  251. { fclose(fp);
  252. return 1;
  253. }
  254. }
  255. #endif
  256. int rename_file(char *from_name, char *from_old, size_t from_size,
  257. char *to_name, char *to_old, size_t to_size)
  258. {
  259. process_file_name(from_name, from_old, from_size);
  260. process_file_name(to_name, to_old, to_size);
  261. if (*from_name == 0 || *to_name == 0) return 0;
  262. return rename(from_name,to_name);
  263. }
  264. #ifdef NAG_VERSION
  265. int list_directory_members(char *filename, char *old, char **filelist[],
  266. size_t n)
  267. { struct dirent **namelist;
  268. int number_of_entries, i;
  269. char **files;
  270. process_file_name(filename, old, n);
  271. /* scandir expects "." for the current directory */
  272. if (*filename == 0) number_of_entries = scandir(".",&namelist,NULL,NULL);
  273. else number_of_entries = scandir(filename,&namelist,NULL,NULL);
  274. /*
  275. * If the scandir failed then return now, since we make an assumption later
  276. * that we found at least two entries: "." and "..".
  277. */
  278. if (number_of_entries == -1) return -1;
  279. files=(char **)malloc(number_of_entries*sizeof(char *));
  280. for (i=0;i<number_of_entries;++i)
  281. { files[i] = strdup(namelist[i]->d_name);
  282. free(namelist[i]);
  283. }
  284. free(namelist);
  285. *filelist = files;
  286. /*
  287. * When we return we will prepend the directory name to the files, so we
  288. * must make sure it is suitable for that. This is done here since it is
  289. * platform dependent (i.e. in DOS we would need to ensure the last
  290. * character was "\").
  291. */
  292. /*
  293. i=strlen(filename);
  294. if (i > 0 && filename[i-1] != '/')
  295. { filename[i]='/';
  296. filename[i+1]='\0';
  297. }
  298. */
  299. return number_of_entries;
  300. }
  301. #else
  302. void list_directory_members(char *filename, char *old,
  303. size_t n, directory_callback *fn)
  304. {
  305. process_file_name(filename, old, n);
  306. scan_files(filename, fn);
  307. }
  308. #endif
  309. CSLbool file_exists(char *filename, char *old, size_t n, char *tt)
  310. /*
  311. * This returns YES if the file exists, and as a side-effect copies a
  312. * textual form of the last-changed-time of the file into the buffer tt.
  313. */
  314. {
  315. struct stat statbuff;
  316. process_file_name(filename, old, n);
  317. if (*filename == 0) return NO;
  318. if (stat(filename, &statbuff) != 0) return NO;
  319. strcpy(tt, ctime(&(statbuff.st_mtime)));
  320. return YES;
  321. }
  322. /*
  323. * getenv() is a mild pain in two respects - firstly Ultrix uses
  324. * a non-ANSI definition (using 2 args not 1), and the MSDOS seems
  325. * to have a strong preference for upper case names. To allow for
  326. * all this I do not call getenv() directly but go via the following
  327. * code that can patch things up.
  328. */
  329. #ifdef TWO_ARG_GETENV
  330. char *my_getenv(char *s)
  331. {
  332. static char value[LONGEST_LEGAL_FILENAME];
  333. getenv(s, value);
  334. return value;
  335. }
  336. #else
  337. char *my_getenv(char *s)
  338. {
  339. return getenv(s);
  340. }
  341. #endif
  342. int my_system(char *s)
  343. {
  344. return system(s);
  345. }
  346. FILE *my_popen(char *a, char *b)
  347. {
  348. #ifdef NCC_LIB
  349. return NULL;
  350. #else
  351. return (FILE *)popen(a, b);
  352. #endif
  353. }
  354. void my_pclose(FILE *a)
  355. {
  356. #ifndef NCC_LIB
  357. pclose(a);
  358. #endif
  359. }
  360. /*
  361. * I do not expect that the following will work exactly unchanged
  362. * on all possible versions of Unix - e.g. header file names may need
  363. * altering and suchlike mess. But the idea should be reasonable and
  364. * changes when needed ought to be small.
  365. */
  366. #ifdef USE_GETUID
  367. /*
  368. * "machine.h" should set USE_GETUID if that is a good way of doing things.
  369. * This is NOT made the default, since it seems that getuid and getpwuid
  370. * are distinctly not comfortably available on all systems. The alternative
  371. * of using getenv("HOME") when expanding "~/xxx" is reasonably good, but
  372. * for "~user/xxx" I give up and just look in the current directory.
  373. */
  374. #include <pwd.h>
  375. extern int getuid(void);
  376. int void get_home_directory(char *b, int len)
  377. {
  378. int i;
  379. struct passwd *pw = getpwuid(getuid());
  380. strcpy(b, pw->pw_dir);
  381. i = strlen(b);
  382. /* Here the directory handed back has "/" forced in as its final character */
  383. if ( b[i-1] != '/')
  384. { b[i++] = '/';
  385. b[i] = 0;
  386. }
  387. return i;
  388. }
  389. int get_users_home_directory(char *b, int len)
  390. {
  391. struct passwd *pw = getpwnam(b);
  392. if (pw != NULL) strcpy(b, pw->pw_dir);
  393. else strcpy(b, "."); /* use current directory if getpwnam() fails */
  394. return strlen(b);
  395. }
  396. #else /* USE_GETUID */
  397. int get_home_directory(char *b, int len)
  398. {
  399. int i;
  400. strcpy(b, getenv("HOME")); /* Probably works with most shells */
  401. i = strlen(b);
  402. if ( b[i-1] != '/')
  403. { b[i++] = '/';
  404. b[i] = 0;
  405. }
  406. return i;
  407. }
  408. int get_users_home_directory(char *b, int len)
  409. {
  410. strcpy(b, "."); /* use current directory if getpwnam() no available */
  411. return 1;
  412. }
  413. #endif /* USE_GETUID */
  414. #ifdef UNIX_TIMES
  415. /*
  416. * This is a BSD-style clock facility, possibly giving a resolution of
  417. * only 1/100 second. I believe that Portable Standard Lisp typically
  418. * reports user time, which is why I do this. A further nasty here
  419. * is that I am probably compiling this file in ANSI mode, and on
  420. * at least some computers this makes #include <sys/times.h> fairly
  421. * ineffective (ugh), so I declare all the structures and functions I
  422. * want directly (ugh ugh) and hope they are as needed. Consider this
  423. * when you port to a new machine.
  424. */
  425. clock_t read_clock(void)
  426. {
  427. struct my_tms {
  428. clock_t tms_utime;
  429. clock_t tms_stime;
  430. clock_t tms_cutime;
  431. clock_t tms_cstime;
  432. } tmsbuf;
  433. clock_t w1, w2, w3;
  434. extern void times(/*struct my_tms * */);
  435. times(&tmsbuf);
  436. w1 = tmsbuf.tms_utime; /* User time in UNIX_TIMES ticks */
  437. w2 = CLOCKS_PER_SEC;
  438. w3 = UNIX_TIMES;
  439. return (clock_t)((double)w1 * ((double)w2/(double)w3));
  440. }
  441. #endif
  442. #ifdef __kcm
  443. extern int _ttyhandle;
  444. int batchp(void)
  445. {
  446. return (_ttyhandle != 0);
  447. }
  448. #else
  449. #ifdef NCC_LIB
  450. int batchp(void)
  451. {
  452. extern int _fisatty(FILE*);
  453. return !_fisatty(stdin);
  454. }
  455. #else
  456. #if BSD_LIB
  457. int batchp(void)
  458. {
  459. return !isatty(fileno(stdin));
  460. }
  461. #else
  462. #error "Unknown Library type"
  463. #endif /* BSD_LIB */
  464. #endif /* NCC_LIB */
  465. #endif /* __kcm */
  466. /*
  467. * The next procedure is responsible for establishing information about
  468. * where the main checkpoint image should be recovered from, and where
  469. * and fasl files should come from.
  470. */
  471. char *find_image_directory(int argc, char *argv[])
  472. {
  473. char image[LONGEST_LEGAL_FILENAME];
  474. char pgmname[LONGEST_LEGAL_FILENAME];
  475. char *w;
  476. /*
  477. * Here I assume Unix, or something sufficiently like it, and
  478. * if the current program is called xxx, then I want an environment
  479. * variable called xxx.img to tell me where to find the image file
  480. * and the fasl directory.
  481. */
  482. #ifdef PUBLIC
  483. strcpy(pgmname, "/usr/local/lib/reduce"); /* fixed name */
  484. w = my_getenv("reduceimg");
  485. if (w != NULL) strcpy(image, w);
  486. else strcpy(image, pgmname);
  487. #else
  488. if (argc > 0 && argv[0] != NULL)
  489. { int i;
  490. w = argv[0];
  491. i = strlen(w);
  492. while (i > 0 && w[i-1] != '/') i--;
  493. sprintf(pgmname, "%s.img", &w[i]); /* final component of argv[0] */
  494. strncpy(program_name, &w[i], 63);
  495. program_name[63] = 0;
  496. }
  497. else strcpy(pgmname, "csl.img"); /* even argv[0] is not available! */
  498. w = my_getenv(pgmname);
  499. #endif
  500. if (w != NULL) strcpy(image, w);
  501. else strcpy(image, pgmname);
  502. /*
  503. * I copy from local vectors into malloc'd space to hand my
  504. * answer back.
  505. */
  506. w = (char *)malloc(1+strlen(image));
  507. /*
  508. * The error exit here seem unsatisfactory...
  509. */
  510. if (w == NULL)
  511. { fprintf(stderr, "\n+++ Panic - run out of space\n");
  512. exit(EXIT_FAILURE);
  513. }
  514. strcpy(w, image);
  515. return w;
  516. }
  517. /*
  518. * The following function controls memory allocation policy
  519. */
  520. int32 ok_to_grab_memory(int32 current)
  521. {
  522. #ifdef COMMON
  523. return current;
  524. #else
  525. return 3*current + 2;
  526. #endif
  527. }
  528. #include "fileops.c"
  529. #include "scandir.c"
  530. /* **************** THIS TICKER STUFF IS NOT WORKING CORRECTLY ******* */
  531. #ifndef SOFTWARE_TICKS
  532. #include <sys/time.h>
  533. struct itimerval value, ovalue;
  534. #endif
  535. static CSLbool ticker_active = NO;
  536. void add_ticker(void)
  537. {
  538. void wimp_tick(int);
  539. /*putc('+', stderr); */
  540. if (ticker_active) return;
  541. #ifdef SOFTWARE_TICKS
  542. if (countdown<0) countdown = SOFTWARE_TICKS; /* Reset if expired */
  543. #else
  544. value.it_interval.tv_sec = 1;
  545. value.it_interval.tv_usec = 0;
  546. value.it_value.tv_sec = 1;
  547. value.it_value.tv_usec = 0;
  548. setitimer(ITIMER_VIRTUAL, &value, NULL); /* Set up a 1 sec interrupt */
  549. signal(SIGVTALRM, wimp_tick);
  550. #endif
  551. ticker_active = YES;
  552. }
  553. void remove_ticker(void)
  554. {
  555. /*putc('-', stderr); */
  556. if (!ticker_active) return;
  557. #ifndef SOFTWARE_TICKS
  558. value.it_interval.tv_sec = 0;
  559. value.it_interval.tv_usec = 0;
  560. value.it_value.tv_sec = 0;
  561. value.it_value.tv_usec = 0;
  562. setitimer(ITIMER_VIRTUAL, &value, NULL); /* Remove all interrupt */
  563. signal(SIGVTALRM, SIG_IGN); /* Ignore the clock ticks */
  564. #endif
  565. ticker_active = NO;
  566. }
  567. #ifndef SOFTWARE_TICKS
  568. void wimp_tick(int sig)
  569. {
  570. /* putc('.', stderr);*/
  571. if (!ticker_active) return;
  572. signal(SIGVTALRM, wimp_tick);
  573. if (tick_pending) return;
  574. else if (already_in_gc) tick_on_gc_exit = YES;
  575. else {
  576. Lisp_Object nil = C_nil;
  577. tick_pending = YES;
  578. saveheaplimit = heaplimit;
  579. heaplimit = fringe;
  580. savevheaplimit = vheaplimit;
  581. vheaplimit = vfringe;
  582. savecodelimit = codelimit;
  583. codelimit = codefringe;
  584. savestacklimit = stacklimit;
  585. stacklimit = stackbase;
  586. }
  587. return;
  588. }
  589. #endif
  590. /* ************************************************************ */
  591. /* ********** StdWin Interface ******************************** */
  592. /* ************************************************************ */
  593. /* ************************************************************ */
  594. #include "stdwin.h"
  595. #include "tools.h"
  596. #include "editwin.h"
  597. #include "text.h" /* Rather a cheat as I need to look
  598. * low down in here */
  599. static WINDOW *CSL_window;
  600. static EDITWIN *CSL_ew;
  601. static EDITWIN *help_ew;
  602. int max_nlines = 250;
  603. #ifndef HELP_DATA
  604. #define HELP_DATA "help.data"
  605. #endif
  606. #ifndef HELP_INDEX
  607. #define HELP_INDEX "help.index"
  608. #endif
  609. static MENU *adminmenu;
  610. static MENU *editmenu;
  611. static MENU *loadmenu;
  612. static MENU *libmenu;
  613. static MENU *switchmenu;
  614. static MENU *helpmenu;
  615. /* static MENU *fontmenu; */
  616. /* static MENU *sizemenu; */
  617. #define ADMIN_MENU (1)
  618. #define MMFile 0
  619. #define MMSaveas 1
  620. #define MMHelp 2 /* main window menu items */
  621. #define MMHelpSel 3
  622. #define MMHelpAsk 4
  623. #define MMInt 5
  624. #define MMAbort 6
  625. #define MMPause 7
  626. #define MMDummy 8
  627. #define MMTime 9
  628. #define MMSpace 10
  629. #define MMOTime 11
  630. #define EDIT_MENU (2)
  631. #define MMCut 0
  632. #define MMCopy 1
  633. #define MMPaste 2
  634. #define MMClear 3
  635. #define MMSelAll 4
  636. #define HELP_LEN (36)
  637. #define HELP_MENU (3)
  638. static struct hlp {
  639. char name[HELP_LEN];
  640. long offset;
  641. int length;
  642. } *hlp;
  643. int help_length;
  644. int helpstamp;
  645. #define LOAD_MENU (4)
  646. static char *loads[] = {
  647. "arnum", "assist", "CSLboolean", "changevr", "compact", "complex",
  648. "decompos", "defint", "dfpart", "elem", "excalc", "gentran", "groebner",
  649. "gnuplot",
  650. "laplace", "linalg", "normform", "numeric", "odesolve", "residue",
  651. "rlfi", "rsolve", "scope", "sets", "specfn", "taylor", "tps", "tri",
  652. "trigsimp", "zeilberg",
  653. (char*)NULL};
  654. #define LIB_MENU (5)
  655. static char *libraries[] = {
  656. "algint", "applysym", "avector", "cali", "camal", "crack", "cvit",
  657. "desir", "dummy", "fide", "fps", "ideals", "ineq", "invbase", "lie",
  658. "modsr", "ncpoly", "orthovec", "physop", "pmrules", "randpoly",
  659. "reacteqn", "spde", "symmetry", "wu", "xcolor", "xideal", "ztrans",
  660. (char*)NULL};
  661. #define SWITCH_MENU (6)
  662. static struct sw {
  663. char *name;
  664. int state;
  665. } switches[] = {
  666. {"algint", NO}, {"adjprec", NO}, {"allbranch", NO}, {"allfac", YES},
  667. {"arbvars", NO}, {"asterisk", YES}, {"backtrace", NO},
  668. {"balanced_mod", NO},{"bfspace", NO}, {"combineexpt", NO},
  669. {"combinelogs", NO}, {"comp", NO}, {"complex", NO},
  670. {"compxroots", NO}, {"cramer", NO}, {"cref", NO}, {"defn", NO},
  671. {"demo", NO}, {"dfprint", NO}, {"div", NO}, {"echo", NO},
  672. {"errcont", NO}, {"evallhseqp", NO}, {"exp", YES},
  673. {"expandexpt", YES}, {"expandlogs", NO}, {"ezgcd", NO},
  674. {"factor", NO}, {"fastfor", NO}, {"force", NO}, {"fort", NO},
  675. {"fortupper", NO}, {"fullprec", NO},{"fullprecision", NO},
  676. {"fullroots", NO}, {"gcd", NO}, {"heugcd", NO}, {"horner", NO},
  677. {"ifactor", NO}, {"int", NO}, {"intstr", NO}, {"lcm", YES},
  678. {"lessspace", NO}, {"limitedfactors", NO}, {"list", NO},
  679. {"listargs", NO}, {"lower", YES}, {"mcd", YES}, {"modular", NO},
  680. {"msg", YES}, {"multiplicities", NO}, {"nat", YES},
  681. {"nero", NO}, {"noarg", YES}, {"noconvert", NO}, {"nonlnr", NO},
  682. {"nosplit", YES}, {"numval", YES}, {"output", YES}, {"period", YES},
  683. {"pgwd", NO}, {"plap", NO}, {"precise", YES},
  684. {"pret", NO}, {"pri", YES}, {"pwrds", YES},
  685. {"quotenewnam", YES},{"raise", NO}, {"rat", NO}, {"ratarg", NO},
  686. {"rational", NO}, {"rationalize", NO}, {"ratpri", YES},
  687. {"reduced", NO}, {"revpri", NO}, {"rlisp88", NO}, {"rootmsg", NO},
  688. {"roundall", YES}, {"roundbf", NO}, {"rounded", NO},
  689. {"savestructr", NO}, {"solvesingular", NO}, {"time", NO},
  690. {"trallfac", NO}, {"trfac", NO}, {"trint", NO}, {"trroot", NO},
  691. {(char*)NULL, 0}};
  692. static void menusetup(void)
  693. {
  694. MENU *mp;
  695. int i;
  696. adminmenu= mp= wmenucreate(ADMIN_MENU, "Admin");
  697. wmenuadditem(mp, "Input file...", 'F');
  698. wmenuadditem(mp, "Saveas...", -1);
  699. wmenuadditem(mp, "Help Window", 'H');
  700. wmenuadditem(mp, "Help Selection", 'S');
  701. wmenuadditem(mp, "Help Topic...", -1);
  702. wmenuadditem(mp, "Interrupt", 'I');
  703. wmenuadditem(mp, "Quit", 'Q');
  704. wmenuadditem(mp, "Pause", 'P');
  705. wmenuadditem(mp, "---------", -1);
  706. wmenuadditem(mp, "0.00", -1);
  707. wmenuadditem(mp, "[GC 0]", -1);
  708. wmenuadditem(mp, "", -1);
  709. wmenuadditem(mp, "", -1);
  710. wmenuenable(mp, MMDummy, NO);
  711. wmenuenable(mp, MMTime, NO);
  712. wmenuenable(mp, MMSpace, NO);
  713. wmenuenable(mp, MMOTime, NO);
  714. editmenu= mp= wmenucreate(EDIT_MENU, "Edit");
  715. wmenuadditem(mp, "Cut", 'X');
  716. wmenuadditem(mp, "Copy", 'C');
  717. wmenuadditem(mp, "Paste", 'V');
  718. wmenuadditem(mp, "Clear", 'B');
  719. wmenuadditem(mp, "Select All", 'A');
  720. helpmenu= mp= wmenucreate(HELP_MENU, "Help");
  721. {
  722. FILE* hlpindx = fopen(HELP_INDEX, "r");
  723. if (hlpindx != NULL) {
  724. fscanf(hlpindx, "%d\n", &helpstamp);
  725. fscanf(hlpindx, "%d", &help_length);
  726. hlp = (struct hlp*) calloc(1+help_length, sizeof(struct hlp));
  727. if (hlp == NULL) {
  728. help_length = 0;
  729. goto loader; /* Insufficient memory */
  730. }
  731. for (i=0; i<help_length; i++) {
  732. int ch, p=0;
  733. fscanf(hlpindx, "%d %d ", &(hlp[i].offset), &(hlp[i].length));
  734. while (p<HELP_LEN-1) {
  735. ch = getc(hlpindx);
  736. if (ch == '\n') break;
  737. hlp[i].name[p++] = ch; /* Was toupper here */
  738. }
  739. while (ch != '\n') ch = getc(hlpindx);
  740. hlp[i].name[p] = '\0';
  741. wmenuadditem(mp, hlp[i].name, -1);
  742. }
  743. fclose(hlpindx);
  744. }
  745. else {
  746. help_length = 0;
  747. strcpy(hlp[0].name, "No help");
  748. hlp[0].offset = -1;
  749. hlp[0].length = 0;
  750. }
  751. }
  752. loader:
  753. loadmenu= mp= wmenucreate(LOAD_MENU, "Load");
  754. for (i=0; loads[i]!= NULL; i++)
  755. wmenuadditem(mp, loads[i], -1);
  756. libmenu= mp= wmenucreate(LIB_MENU, "Library");
  757. for (i=0; libraries[i]!= NULL; i++)
  758. wmenuadditem(mp, libraries[i], -1);
  759. switchmenu= mp= wmenucreate(SWITCH_MENU, "Switch");
  760. for (i=0; switches[i].name!= NULL; i++) {
  761. wmenuadditem(mp, switches[i].name, -1);
  762. wmenucheck(mp, i, switches[i].state);
  763. }
  764. }
  765. static fixmenus(void)
  766. {
  767. CSLbool focus;
  768. focus= (CSL_ew->tp->foclen != 0);
  769. wmenuenable(editmenu, MMCut, focus);
  770. wmenuenable(editmenu, MMCopy, focus);
  771. wmenuenable(editmenu, MMClear, focus);
  772. wmenuenable(adminmenu, MMHelpSel, focus);
  773. /* wmenuenable(editmenu, MMPaste, YES); */
  774. if (help_ew != NULL) {
  775. focus= (help_ew->tp->foclen != 0);
  776. if (focus) {
  777. wmenuenable(editmenu, MMCut, focus);
  778. wmenuenable(editmenu, MMCopy, focus);
  779. wmenuenable(editmenu, MMClear, focus);
  780. wmenuenable(adminmenu, MMHelpSel, focus);
  781. }
  782. }
  783. }
  784. #define TTYBUF_SIZE 256
  785. static char tty_buff[TTYBUF_SIZE];
  786. static int tty_index = 0;
  787. static CSLbool tty_ready = NO;
  788. static int tty_nnl = 0;
  789. static int tty_offset;
  790. #define STDOUT_BUFSIZE 1024
  791. #define LONGEST_PRINTF 120
  792. static char stdout_buffer[STDOUT_BUFSIZE];
  793. static char *stdout_p;
  794. static int stdout_n;
  795. void start_up_window_manager(int use_wimp)
  796. {
  797. static char* def_args[]= {"X-Reduce 3.6", (char*)NULL};
  798. int argc= 1;
  799. char **argv= def_args;
  800. int CSL_width, CSL_height;
  801. signal(SIGVTALRM, SIG_IGN); /* Ensure it is off */
  802. wargs(&argc, &argv); /* Fiddle the argument decode for now */
  803. winit();
  804. wsetfont("6x13"); /* For now */
  805. menusetup();
  806. wsetdefwinsize(82*wcharwidth('0'), 25*wlineheight());
  807. CSL_ew = ewcreate(NULL);
  808. CSL_window = CSL_ew->win;
  809. wsettitle(CSL_window, "Reduce 3.6");
  810. fixmenus();
  811. /* wmenudetach(CSL_window, helpmenu); */
  812. wmenuenable(editmenu, MMTime, NO); /* These are not selectable */
  813. wmenuenable(editmenu, MMOTime, NO); /* These are not selectable */
  814. wmenuenable(editmenu, MMSpace, NO);
  815. wmenudetach(CSL_window, loadmenu); /* These are only valid when reading */
  816. wmenudetach(CSL_window, libmenu);
  817. wmenudetach(CSL_window, switchmenu);
  818. /* wmessage("Welcome to X-Reduce\n\n"); */
  819. wflush();
  820. stdout_n = 0;
  821. stdout_p = stdout_buffer;
  822. #ifndef SOFTWARE_TICKS
  823. value.it_interval.tv_sec = 1;
  824. value.it_interval.tv_usec = 0;
  825. value.it_value.tv_sec = 1; /* ?? 10 seconds */
  826. value.it_value.tv_usec = 0;
  827. signal(SIGVTALRM, wimp_tick);
  828. setitimer(ITIMER_VIRTUAL, &value, NULL); /* Set up a 1 sec interrupt */
  829. #endif
  830. help_ew = NULL; /* Help window */
  831. }
  832. static char *help_buff;
  833. CSLbool
  834. helpwindow(int index)
  835. {
  836. FILE* help = fopen(HELP_DATA, "r");
  837. int ch;
  838. int width, height;
  839. int size = hlp[index].length;
  840. if (help == NULL) return;
  841. /* fprintf(stderr, "Help on index %d offset=%d size=%d\n",
  842. index, hlp[index].offset, hlp[index].length); */
  843. fscanf(help, "%d\n", &ch);
  844. if (ch != helpstamp) return; /* Check help data in in line with index */
  845. fseek(help, hlp[index].offset, SEEK_SET);
  846. if (help_ew) {
  847. free(help_buff);
  848. tesetfocus(help_ew->tp, 0, tegetlen(help_ew->tp));
  849. ewreplace(help_ew, "");
  850. }
  851. else {
  852. help_ew = ewcreate(NULL);
  853. wsettitle(help_ew->win, "Help for Reduce 3.6");
  854. }
  855. help_buff = malloc(size+1);
  856. if (help_buff == NULL) {
  857. dprintf("Insufficient memory");
  858. wfleep();
  859. return FALSE;
  860. }
  861. /* fprintf(stderr, "reading %d bytes to buffer\n", size); */
  862. fread(help_buff, size, 1, help);
  863. /* fprintf(stderr, "help starts as %.100s\n", help_buff); */
  864. help_buff[size] = '\0';
  865. wmenudetach(help_ew->win, loadmenu);
  866. wmenudetach(help_ew->win, libmenu);
  867. wmenudetach(help_ew->win, switchmenu);
  868. /* wmenudetach(help_ew->win, adminmenu); */
  869. ewreplace(help_ew, help_buff);
  870. tesetfocus(help_ew->tp, 0, 0);
  871. fclose(help);
  872. return TRUE;
  873. }
  874. void help_buffer(char *buf, int len)
  875. {
  876. int i;
  877. for (i=0; i<help_length; i++) {
  878. /* fprintf(stderr, "Check against %s\n", hlp[i].name); */
  879. if (strncmp(hlp[i].name, buf, len) == 0) {
  880. helpwindow(i);
  881. break;
  882. }
  883. }
  884. if (i == help_length) wfleep();
  885. }
  886. void help_selection(EDITWIN *ew)
  887. {
  888. int i;
  889. char *text;
  890. TEXTEDIT *tp = ew->tp;
  891. if (tp->foclen == 0) {
  892. wfleep();
  893. return;
  894. }
  895. text= tegettext(tp);
  896. help_buffer(text+tp->foc, tp->foclen);
  897. }
  898. extern int pause_set = 0;
  899. void event_loop(void)
  900. {
  901. for (;;) { /* Loop while there are events */
  902. EVENT e;
  903. EDITWIN *ew;
  904. CSLbool closed;
  905. /* putc('%', stderr); */
  906. wgetevent(&e);
  907. /* printf("Event: type=%d win=%p data=%d\n", e.type, e.window, e.u.command); */
  908. ew = ewfind(e.window);
  909. if (ew == CSL_ew) {
  910. switch (e.type) {
  911. case WE_CHAR:
  912. switch(e.u.character) {
  913. case 'A'-'@': /* ^A == beginning of line */
  914. {
  915. TEXTEDIT* tp = CSL_ew->tp;
  916. tesetfocus(tp,
  917. zsubgap(tp->start[tewhichline(tp,
  918. zaddgap(tp->foc),
  919. tp->focprev)]),
  920. -1);
  921. break;
  922. }
  923. case 'B'-'@': /* ^B back a character */
  924. tearrow(CSL_ew->tp, WC_LEFT);
  925. break;
  926. case 127: /* Delete character */
  927. case 'D'-'@': /* ^D delete at cursor */
  928. {
  929. TEXTEDIT* tp = CSL_ew->tp;
  930. tearrow(tp, WC_RIGHT);
  931. {
  932. int f1 = tp->foc;
  933. int i;
  934. int ss = tp->start[tp->nlines-tty_nnl];
  935. int ee = ss + tty_offset;
  936. if (ss <= f1 && f1 < ee) {
  937. if (tty_offset>0) tty_offset--;
  938. }
  939. e.type = WE_COMMAND;
  940. e.u.command = WC_BACKSPACE;
  941. ewevent(ew,&e, NULL);
  942. break;
  943. }
  944. }
  945. case 'E'-'@': /* ^E end of line */
  946. {
  947. TEXTEDIT* tp = CSL_ew->tp;
  948. int line = tewhichline(tp, zaddgap(tp->foc), tp->focprev);
  949. int xxx = zsubgap(tetextround(tp, line, tp->right));
  950. tesetfocus(tp, xxx, -1);
  951. break;
  952. }
  953. case 'F'-'@': /* ^F forward a character */
  954. tearrow(CSL_ew->tp, WC_RIGHT);
  955. break;
  956. case 'K'-'@': /* ^K kill to end of line */
  957. { /* This does not take notice of offset */
  958. TEXTEDIT* tp = CSL_ew->tp;
  959. int f1;
  960. int i;
  961. int ss;
  962. int ee;
  963. tesetfocus(tp,
  964. tp->foc,
  965. zsubgap(tetextround(tp,
  966. tewhichline(tp, zaddgap(tp->foc),
  967. tp->focprev),
  968. tp->right)));
  969. f1 = tp->foc;
  970. ss = tp->start[tp->nlines-tty_nnl];
  971. ee = ss + tty_offset;
  972. for (i=0; i<tp->foclen; i++)
  973. if (ss <= f1+i && f1+i < ee) {
  974. if (tty_offset>0) tty_offset--;
  975. }
  976. ewreplace(ew, "");
  977. break;
  978. }
  979. case 'N'-'@': /* ^N next line */
  980. tearrow(CSL_ew->tp, WC_DOWN);
  981. break;
  982. case 'P'-'@': /* ^P previous line */
  983. tearrow(CSL_ew->tp, WC_UP);
  984. break;
  985. case 'Z'-'@': /* ^Z move to end of buffer */
  986. {
  987. TEXTEDIT* tp = CSL_ew->tp;
  988. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  989. break;
  990. }
  991. default:
  992. ewevent(ew, &e, &closed);
  993. if (tty_ready == YES && !pause_set) return;
  994. }
  995. break;
  996. case WE_COMMAND:
  997. switch (e.u.command) {
  998. case WC_CANCEL:
  999. interrupt_pending = YES;
  1000. break;
  1001. case WC_CLOSE:
  1002. pause_for_user();
  1003. exit(1);
  1004. case WC_RETURN:
  1005. {
  1006. TEXTEDIT* tp = CSL_ew->tp;
  1007. int f1 = zaddgap(tp->foc);
  1008. int ee = tp->start[tp->nlines-tty_nnl] + tty_offset;
  1009. /* printf("f1=%d ee=%d offset=%d\n", f1, ee, tty_offset); */
  1010. if (f1 >= ee) {
  1011. tty_nnl++;
  1012. if (f1 == tp->buflen) {
  1013. ewevent(ew, &e, &closed);
  1014. tty_ready = YES;
  1015. if (!pause_set) return;
  1016. }
  1017. }
  1018. }
  1019. break;
  1020. case WC_DEL:
  1021. case WC_BACKSPACE:
  1022. /* Need to check to see if we are deleting
  1023. * in the offset area */
  1024. {
  1025. TEXTEDIT* tp = CSL_ew->tp;
  1026. int f1 = tp->foc;
  1027. int i;
  1028. int ss = tp->start[tp->nlines-tty_nnl];
  1029. int ee = ss + tty_offset;
  1030. if (tp->foclen == 0) {
  1031. if (ss < f1 && f1 <= ee && tty_offset>0) tty_offset--;
  1032. }
  1033. else {
  1034. for (i=0; i<tp->foclen; i++) {
  1035. if (ss <= f1+i && f1+i < ee && tty_offset>0) tty_offset--;
  1036. }
  1037. }
  1038. }
  1039. break;
  1040. case WC_LEFT:
  1041. case WC_RIGHT:
  1042. default:
  1043. break;
  1044. }
  1045. ewevent(ew, &e, &closed);
  1046. break;
  1047. case WE_MENU:
  1048. switch (e.u.m.id) {
  1049. case ADMIN_MENU:
  1050. switch (e.u.m.item) {
  1051. case MMFile:
  1052. {
  1053. short wd;
  1054. TEXTEDIT *tp = CSL_ew->tp;
  1055. char name[42];
  1056. if (waskstr("Input file name", name, 40)) {
  1057. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1058. ewreplace(CSL_ew, "in \"");
  1059. ewreplace(CSL_ew, name);
  1060. ewreplace(CSL_ew, "\"");
  1061. /*tetoend(tp); */
  1062. }
  1063. break;
  1064. }
  1065. case MMSaveas:
  1066. ewsaveas(CSL_ew);
  1067. break;
  1068. case MMHelp:
  1069. helpwindow(0);
  1070. break;
  1071. case MMHelpSel:
  1072. help_selection(ew);
  1073. break;
  1074. case MMHelpAsk:
  1075. {
  1076. char buf[40];
  1077. int len;
  1078. if (waskstr("Help on topic", buf, 40)) {
  1079. len = strlen(buf);
  1080. help_buffer(buf, len);
  1081. }
  1082. }
  1083. break;
  1084. case MMAbort:
  1085. pause_for_user();
  1086. exit(1);
  1087. case MMInt:
  1088. interrupt_pending = YES;
  1089. return;
  1090. case MMPause:
  1091. pause_set = !pause_set;
  1092. wmenucheck(adminmenu, MMPause, pause_set);
  1093. if (pause_set) wsettitle(CSL_window, "<Paused> Reduce 3.6");
  1094. else wsettitle(CSL_window, "Reduce 3.6");
  1095. break;
  1096. }
  1097. break;
  1098. case EDIT_MENU:
  1099. switch (e.u.m.item) {
  1100. case MMCopy:
  1101. ewcopy(ew);
  1102. break;
  1103. case MMPaste:
  1104. {
  1105. char* text = wgetclip();
  1106. char* tt = text;
  1107. int valid = YES;
  1108. if (text == NULL) wfleep();
  1109. else {
  1110. TEXTEDIT *tp = CSL_ew->tp;
  1111. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1112. while (*tt != '\0')
  1113. if (*tt++=='\n') valid = NO;
  1114. if (valid) ewreplace(ew, text);
  1115. else wmessage("Cannot Paste text including new line");
  1116. }
  1117. }
  1118. break;
  1119. case MMCut:
  1120. ewcopy(ew);
  1121. case MMClear:
  1122. /* Need to check to see if we are deleting
  1123. * in the offset area */
  1124. {
  1125. TEXTEDIT* tp = CSL_ew->tp;
  1126. int f1 = tp->foc;
  1127. int i;
  1128. int ss = tp->start[tp->nlines-tty_nnl];
  1129. int ee = ss + tty_offset;
  1130. for (i=0; i<tp->foclen; i++)
  1131. if (ss <= f1+i && f1+i < ee) {
  1132. if (tty_offset>0) tty_offset--;
  1133. }
  1134. }
  1135. ewreplace(ew, "");
  1136. break;
  1137. case MMSelAll:
  1138. tesetfocus(ew->tp, 0, tegetlen(ew->tp));
  1139. break;
  1140. }
  1141. break;
  1142. case LOAD_MENU:
  1143. {
  1144. char *load = "load_package ";
  1145. char *tt = loads[e.u.m.item];
  1146. TEXTEDIT *tp = CSL_ew->tp;
  1147. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1148. tp->aim= UNDEF;
  1149. tp->focprev= FALSE;
  1150. ewreplace(CSL_ew, load);
  1151. ewreplace(CSL_ew, tt);
  1152. tty_ready = YES;
  1153. ewreplace(CSL_ew, ";\n");
  1154. tty_nnl++;
  1155. wmenuenable(loadmenu, e.u.m.item, NO);
  1156. return;
  1157. }
  1158. case LIB_MENU:
  1159. {
  1160. char *load = "load_package ";
  1161. char *tt = libraries[e.u.m.item];
  1162. TEXTEDIT *tp = CSL_ew->tp;
  1163. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1164. tp->aim= UNDEF;
  1165. tp->focprev= FALSE;
  1166. ewreplace(CSL_ew, load);
  1167. ewreplace(CSL_ew, tt);
  1168. tty_ready = YES;
  1169. ewreplace(CSL_ew, ";\n");
  1170. tty_nnl++;
  1171. wmenuenable(loadmenu, e.u.m.item, NO);
  1172. return;
  1173. }
  1174. case SWITCH_MENU:
  1175. {
  1176. char *load = (switches[e.u.m.item].state ? "off " : "on ");
  1177. char *tt = switches[e.u.m.item].name;
  1178. TEXTEDIT *tp = CSL_ew->tp;
  1179. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1180. ewreplace(CSL_ew, load);
  1181. ewreplace(CSL_ew, tt);
  1182. tty_ready = YES;
  1183. ewreplace(CSL_ew, ";\n");
  1184. tty_nnl++;
  1185. switches[e.u.m.item].state = ~ switches[e.u.m.item].state;
  1186. wmenucheck(switchmenu, e.u.m.item, switches[e.u.m.item].state);
  1187. return;
  1188. }
  1189. case HELP_MENU:
  1190. helpwindow(e.u.m.item);
  1191. break;
  1192. }
  1193. break;
  1194. case WE_CLOSE:
  1195. pause_for_user();
  1196. exit(1);
  1197. default:
  1198. ewevent(ew, &e, &closed);
  1199. break;
  1200. }
  1201. }
  1202. else if (ew == help_ew) {
  1203. switch (e.type) {
  1204. case WE_MOUSE_UP: /* Extend to a word on single click */
  1205. if (!ew->tp->mdown) break;
  1206. ew->tp->mdown= FALSE;
  1207. if (e.u.where.clicks > 1) {
  1208. teclicknew(ew->tp, e.u.where.h, e.u.where.v, FALSE, TRUE);
  1209. help_selection(ew);
  1210. }
  1211. break;
  1212. case WE_CHAR:
  1213. switch(e.u.character) {
  1214. case 'A'-'@': /* ^A == beginning of line */
  1215. {
  1216. TEXTEDIT* tp = help_ew->tp;
  1217. tesetfocus(tp,
  1218. zsubgap(tp->start[tewhichline(tp,
  1219. zaddgap(tp->foc),
  1220. tp->focprev)]),
  1221. -1);
  1222. break;
  1223. }
  1224. case 'B'-'@': /* ^B back a character */
  1225. tearrow(help_ew->tp, WC_LEFT);
  1226. break;
  1227. case 'E'-'@': /* ^E end of line */
  1228. {
  1229. TEXTEDIT* tp = help_ew->tp;
  1230. int line = tewhichline(tp, zaddgap(tp->foc), tp->focprev);
  1231. int xxx = zsubgap(tetextround(tp, line, tp->right));
  1232. tesetfocus(tp, xxx, -1);
  1233. break;
  1234. }
  1235. case 'F'-'@': /* ^F forward a character */
  1236. tearrow(help_ew->tp, WC_RIGHT);
  1237. break;
  1238. case 'K'-'@': /* ^K is Page up */
  1239. {
  1240. int i;
  1241. int j;
  1242. wgetdefwinsize(&i, &j);
  1243. j = j/wlineheight() -1;
  1244. for (i=0; i<j; i++) tearrow(help_ew->tp, WC_UP);
  1245. break;
  1246. }
  1247. case 'N'-'@': /* ^N next line */
  1248. tearrow(help_ew->tp, WC_DOWN);
  1249. break;
  1250. case 'P'-'@': /* ^P previous line */
  1251. tearrow(help_ew->tp, WC_UP);
  1252. break;
  1253. case 'Z'-'@': /* ^Z move to end of buffer */
  1254. {
  1255. TEXTEDIT* tp = help_ew->tp;
  1256. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1257. break;
  1258. }
  1259. case 'V'-'@': /* ^V page down */
  1260. case ' ':
  1261. case 'L'-'@': /* ^L is Page down */
  1262. {
  1263. int i;
  1264. int j;
  1265. wgetdefwinsize(&i, &j);
  1266. j = j/wlineheight() -1;
  1267. for (i=0; i<j; i++) tearrow(help_ew->tp, WC_DOWN);
  1268. break;
  1269. }
  1270. case 'i':
  1271. case 'I':
  1272. {
  1273. char buf[40];
  1274. int len;
  1275. if (waskstr("Help on topic", buf, 40)) {
  1276. len = strlen(buf);
  1277. help_buffer(buf, len);
  1278. }
  1279. break;
  1280. }
  1281. case 'n':
  1282. case 'N':
  1283. {
  1284. extern char *strstr(const char*, const char*);
  1285. char *p = strstr((const char*)help_buff, (const char*)"Next: ");
  1286. int i = 0;
  1287. if (p == NULL) {
  1288. wfleep(); break;
  1289. }
  1290. p += 6;
  1291. while (p[i]!= ',') i++;
  1292. help_buffer(p,i);
  1293. break;
  1294. }
  1295. case 'p':
  1296. case 'P':
  1297. {
  1298. extern char *strstr(const char*, const char*);
  1299. char *p = strstr((const char*)help_buff, "Prev: ");
  1300. int i = 0;
  1301. if (p == NULL) {
  1302. wfleep(); break;
  1303. }
  1304. p += 6;
  1305. while (p[i]!= ',') i++;
  1306. help_buffer(p,i);
  1307. break;
  1308. }
  1309. case 'q':
  1310. case 'Q':
  1311. help_ew->saved = TRUE; /* Fake it */
  1312. free(help_buff);
  1313. ewclose(help_ew);
  1314. help_ew = 0;
  1315. break;
  1316. case 'u':
  1317. case 'U':
  1318. {
  1319. extern char *strstr(const char*, const char*);
  1320. char *p = strstr((const char*)help_buff, "Up: ");
  1321. int i = 0;
  1322. if (p == NULL) {
  1323. wfleep(); break;
  1324. }
  1325. p += 4;
  1326. while (p[i]!= '\n') i++;
  1327. help_buffer(p,i);
  1328. break;
  1329. }
  1330. }
  1331. break;
  1332. case WE_MENU:
  1333. switch (e.u.m.id) {
  1334. case ADMIN_MENU:
  1335. switch (e.u.m.item) {
  1336. case MMSaveas:
  1337. ewsaveas(help_ew);
  1338. break;
  1339. case MMHelp:
  1340. if (help_length) helpwindow(0);
  1341. break;
  1342. case MMHelpSel:
  1343. help_selection(ew);
  1344. break;
  1345. case MMHelpAsk:
  1346. {
  1347. char buf[40];
  1348. int len;
  1349. if (waskstr("Help on topic", buf, 40)) {
  1350. len = strlen(buf);
  1351. help_buffer(buf, len);
  1352. }
  1353. break;
  1354. }
  1355. case MMAbort:
  1356. help_ew->saved = TRUE; /* Fake it */
  1357. free(help_buff);
  1358. ewclose(help_ew);
  1359. help_ew = 0;
  1360. break;
  1361. }
  1362. break;
  1363. case EDIT_MENU:
  1364. switch (e.u.m.item) {
  1365. case MMCopy:
  1366. ewcopy(ew);
  1367. break;
  1368. case MMSelAll:
  1369. tesetfocus(ew->tp, 0, tegetlen(ew->tp));
  1370. break;
  1371. }
  1372. break;
  1373. case HELP_MENU:
  1374. helpwindow(e.u.m.item);
  1375. break;
  1376. }
  1377. break;
  1378. case WE_COMMAND:
  1379. switch (e.u.command) {
  1380. case WC_CANCEL:
  1381. interrupt_pending=YES;
  1382. break;
  1383. case WC_RETURN:
  1384. help_selection(ew);
  1385. break;
  1386. case WC_DEL:
  1387. case WC_BACKSPACE:
  1388. helpwindow(0);
  1389. break;
  1390. default:
  1391. ewevent(ew, &e, &closed);
  1392. break;
  1393. }
  1394. if (e.u.command != WC_CLOSE) {
  1395. break;
  1396. }
  1397. case WE_CLOSE:
  1398. help_ew->saved = TRUE; /* Fake it */
  1399. free(help_buff);
  1400. ewclose(help_ew);
  1401. help_ew = 0;
  1402. break;
  1403. default:
  1404. ewevent(ew, &e, &closed);
  1405. if (closed) {
  1406. help_ew->saved = TRUE; /* Fake it */
  1407. free(help_buff);
  1408. ewclose(help_ew);
  1409. help_ew = 0;
  1410. }
  1411. break;
  1412. }
  1413. }
  1414. else if (ew != NULL) ewevent(ew, &e, &closed);
  1415. else wfleep();
  1416. fixmenus();
  1417. }
  1418. }
  1419. void poll_for_attn(void)
  1420. {
  1421. EVENT e;
  1422. EDITWIN *ew;
  1423. /* putc('#', stderr); */
  1424. if (!pause_set) {
  1425. if (!wpollevent(&e)) {
  1426. /* putc('<', stderr); */
  1427. return;
  1428. }
  1429. }
  1430. else wgetevent(&e);
  1431. /* fprintf(stderr, "PollEvent: type=%d win=%p data=%d\n", e.type,e.window,e.u.command); */
  1432. for (;;) { /* Loop while there are events */
  1433. CSLbool closed;
  1434. ew = ewfind(e.window);
  1435. if (ew == CSL_ew) {
  1436. switch (e.type) {
  1437. case WE_CHAR:
  1438. switch(e.u.character) {
  1439. case 'A'-'@': /* ^A == beginning of line */
  1440. {
  1441. TEXTEDIT* tp = CSL_ew->tp;
  1442. tesetfocus(tp,
  1443. zsubgap(tp->start[tewhichline(tp,
  1444. zaddgap(tp->foc),
  1445. tp->focprev)]),
  1446. -1);
  1447. break;
  1448. }
  1449. case 'B'-'@': /* ^B back a character */
  1450. tearrow(CSL_ew->tp, WC_LEFT);
  1451. break;
  1452. case 'D'-'@': /* ^D delete at cursor */
  1453. {
  1454. TEXTEDIT* tp = CSL_ew->tp;
  1455. tearrow(tp, WC_RIGHT);
  1456. e.type = WE_COMMAND;
  1457. e.u.command = WC_BACKSPACE;
  1458. ewevent(ew,&e, NULL);
  1459. break;
  1460. }
  1461. case 'E'-'@': /* ^E end of line */
  1462. {
  1463. TEXTEDIT* tp = CSL_ew->tp;
  1464. int line = tewhichline(tp, zaddgap(tp->foc), tp->focprev);
  1465. int xxx = zsubgap(tetextround(tp, line, tp->right));
  1466. tesetfocus(tp, xxx, -1);
  1467. break;
  1468. }
  1469. case 'F'-'@': /* ^F forward a character */
  1470. tearrow(CSL_ew->tp, WC_RIGHT);
  1471. break;
  1472. case 'K'-'@': /* ^K kill all type ahead */
  1473. tty_index = 0;
  1474. break;
  1475. case 'N'-'@': /* ^N next line */
  1476. tearrow(CSL_ew->tp, WC_DOWN);
  1477. break;
  1478. case 'P'-'@': /* ^P previous line */
  1479. tearrow(CSL_ew->tp, WC_UP);
  1480. break;
  1481. case 'Z'-'@': /* ^Z move to end of buffer */
  1482. {
  1483. TEXTEDIT* tp = CSL_ew->tp;
  1484. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1485. break;
  1486. }
  1487. case 'V'-'@': /* ^V page down */
  1488. case ' ':
  1489. {
  1490. int i;
  1491. int j;
  1492. wgetdefwinsize(&i, &j);
  1493. j = j/wlineheight() -1;
  1494. for (i=0; i<j; i++) tearrow(help_ew->tp, WC_DOWN);
  1495. break;
  1496. }
  1497. default:
  1498. if (tty_index > TTYBUF_SIZE-2) wfleep();
  1499. else tty_buff[tty_index++] = e.u.character;
  1500. break;
  1501. }
  1502. break;
  1503. case WE_COMMAND:
  1504. switch (e.u.command) {
  1505. case WC_CANCEL:
  1506. interrupt_pending = YES;
  1507. break;
  1508. case WC_CLOSE:
  1509. pause_for_user();
  1510. exit(1);
  1511. case WC_RETURN:
  1512. if (tty_index > TTYBUF_SIZE-2) wfleep();
  1513. else tty_buff[tty_index++] = '\n';
  1514. break;
  1515. case WC_TAB:
  1516. if (tty_index > TTYBUF_SIZE-2) wfleep();
  1517. else tty_buff[tty_index++] = '\t';
  1518. break;
  1519. case WC_DEL:
  1520. case WC_BACKSPACE:
  1521. if (tty_index>0) tty_index--;
  1522. break;
  1523. }
  1524. break;
  1525. case WE_MENU:
  1526. switch (e.u.m.id) {
  1527. case ADMIN_MENU:
  1528. switch (e.u.m.item) {
  1529. case MMHelp:
  1530. helpwindow(0);
  1531. break;
  1532. case MMHelpSel:
  1533. help_selection(ew);
  1534. break;
  1535. case MMAbort:
  1536. pause_for_user();
  1537. exit(1);
  1538. case MMInt:
  1539. interrupt_pending = YES;
  1540. return;
  1541. case MMPause:
  1542. pause_set = !pause_set;
  1543. wmenucheck(adminmenu, MMPause, pause_set);
  1544. if (pause_set) wsettitle(CSL_window, "<Paused> Reduce 3.6");
  1545. else wsettitle(CSL_window, "Reduce 3.6");
  1546. break;
  1547. }
  1548. break;
  1549. case EDIT_MENU:
  1550. switch (e.u.m.item) {
  1551. case MMCopy:
  1552. ewcopy(ew);
  1553. break;
  1554. case MMPaste:
  1555. break;
  1556. case MMCut:
  1557. ewcopy(ew);
  1558. case MMClear:
  1559. ewreplace(ew, "");
  1560. break;
  1561. case MMSelAll:
  1562. tesetfocus(ew->tp, 0, tegetlen(ew->tp));
  1563. break;
  1564. }
  1565. break;
  1566. case HELP_MENU:
  1567. helpwindow(e.u.m.item);
  1568. break;
  1569. }
  1570. break;
  1571. case WE_CLOSE:
  1572. pause_for_user();
  1573. exit(1);
  1574. default:
  1575. ewevent(ew, &e, &closed);
  1576. break;
  1577. }
  1578. }
  1579. else if (ew == help_ew) {
  1580. switch (e.type) {
  1581. case WE_MOUSE_UP: /* Extend to a word on single click */
  1582. if (!ew->tp->mdown)
  1583. break;
  1584. ew->tp->mdown= FALSE;
  1585. if (e.u.where.clicks > 1) {
  1586. teclicknew(ew->tp, e.u.where.h, e.u.where.v, FALSE, TRUE);
  1587. help_selection(ew);
  1588. }
  1589. break;
  1590. case WE_CHAR:
  1591. /* fprintf(stderr, "WE_CHAR %d(%c)\n", e.u.character,e.u.character); */
  1592. switch(e.u.character) {
  1593. case 'A'-'@': /* ^A == beginning of line */
  1594. {
  1595. TEXTEDIT* tp = help_ew->tp;
  1596. tesetfocus(tp,
  1597. zsubgap(tp->start[tewhichline(tp,
  1598. zaddgap(tp->foc),
  1599. tp->focprev)]),
  1600. -1);
  1601. break;
  1602. }
  1603. case 'B'-'@': /* ^B back a character */
  1604. tearrow(help_ew->tp, WC_LEFT);
  1605. break;
  1606. case 'E'-'@': /* ^E end of line */
  1607. {
  1608. TEXTEDIT* tp = help_ew->tp;
  1609. int line = tewhichline(tp, zaddgap(tp->foc), tp->focprev);
  1610. int xxx = zsubgap(tetextround(tp, line, tp->right));
  1611. tesetfocus(tp, xxx, -1);
  1612. break;
  1613. }
  1614. case 'F'-'@': /* ^F forward a character */
  1615. tearrow(help_ew->tp, WC_RIGHT);
  1616. break;
  1617. case 'N'-'@': /* ^N next line */
  1618. tearrow(help_ew->tp, WC_DOWN);
  1619. break;
  1620. case 'P'-'@': /* ^P previous line */
  1621. tearrow(help_ew->tp, WC_UP);
  1622. break;
  1623. case 'Z'-'@': /* ^Z move to end of buffer */
  1624. {
  1625. TEXTEDIT* tp = help_ew->tp;
  1626. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1627. break;
  1628. }
  1629. case 'L'-'@': /* ^L is PgDn */
  1630. case 'V'-'@': /* ^V page down */
  1631. case ' ':
  1632. {
  1633. int i;
  1634. int j;
  1635. wgetdefwinsize(&i, &j);
  1636. j = j/wlineheight() -1;
  1637. for (i=0; i<j; i++) tearrow(help_ew->tp, WC_DOWN);
  1638. break;
  1639. }
  1640. case 'K'-'@': /* ^K is PgUp */
  1641. {
  1642. int i;
  1643. int j;
  1644. wgetdefwinsize(&i, &j);
  1645. j = j/wlineheight() -1;
  1646. for (i=0; i<j; i++) tearrow(help_ew->tp, WC_UP);
  1647. break;
  1648. }
  1649. }
  1650. break;
  1651. case WE_MENU:
  1652. switch (e.u.m.id) {
  1653. case ADMIN_MENU:
  1654. switch (e.u.m.item) {
  1655. case MMHelp:
  1656. if (help_length) helpwindow(0);
  1657. break;
  1658. case MMHelpSel:
  1659. help_selection(ew);
  1660. break;
  1661. }
  1662. break;
  1663. case EDIT_MENU:
  1664. switch (e.u.m.item) {
  1665. case MMCopy:
  1666. ewcopy(ew);
  1667. break;
  1668. case MMSelAll:
  1669. tesetfocus(ew->tp, 0,
  1670. tegetlen(ew->tp));
  1671. break;
  1672. }
  1673. break;
  1674. case HELP_MENU:
  1675. helpwindow(e.u.m.item);
  1676. break;
  1677. }
  1678. break;
  1679. case WE_COMMAND:
  1680. switch (e.u.command) {
  1681. case WC_CANCEL:
  1682. interrupt_pending = YES;
  1683. break;
  1684. case WC_RETURN:
  1685. help_selection(ew);
  1686. break;
  1687. case WC_DEL:
  1688. case WC_BACKSPACE:
  1689. helpwindow(0);
  1690. break;
  1691. default:
  1692. ewevent(ew, &e, &closed);
  1693. break;
  1694. }
  1695. if (e.u.command != WC_CLOSE) {
  1696. break;
  1697. }
  1698. case WE_CLOSE:
  1699. help_ew->saved = TRUE; /* Fake it */
  1700. free(help_buff);
  1701. ewclose(help_ew);
  1702. help_ew = 0;
  1703. break;
  1704. default:
  1705. ewevent(ew, &e, &closed);
  1706. if (closed) {
  1707. help_ew->saved = TRUE; /* Fake it */
  1708. free(help_buff);
  1709. ewclose(help_ew);
  1710. help_ew = 0;
  1711. }
  1712. break;
  1713. }
  1714. }
  1715. else if (ew != NULL) ewevent(ew, &e, &closed);
  1716. else wfleep();
  1717. fixmenus();
  1718. /* putc('#', stderr); */
  1719. if (!pause_set) {
  1720. if (!wpollevent(&e)) {
  1721. /* putc('<', stderr); */
  1722. return;
  1723. }
  1724. }
  1725. else wgetevent(&e);
  1726. /* fprintf(stderr, "PollEvent: type=%d win=%p data=%d\n", e.type,e.window,e.u.command); */
  1727. }
  1728. }
  1729. void flush_screen(void)
  1730. {
  1731. TEXTEDIT* tp = CSL_ew->tp;
  1732. if (stdout_n != 0) {
  1733. /* fprintf(stderr, stdout_buffer); */
  1734. ewreplace(CSL_ew, stdout_buffer);
  1735. stdout_n = 0; stdout_p = stdout_buffer;
  1736. }
  1737. if (tp->nlines > max_nlines+5) { /* Allow a five line slop */
  1738. techangefocus(tp, 0, zsubgap(tp->start[tp->nlines-max_nlines]));
  1739. tp->aim= UNDEF;
  1740. tp->focprev= FALSE;
  1741. /* ewreplace(CSL_ew, ""); */
  1742. tereplace(tp, "");
  1743. /* fprintf(stderr, "-> %d\n", tp->nlines); */
  1744. /* focus to end */
  1745. tesetfocus(tp, tp->buflen - tp->gaplen, -1);
  1746. }
  1747. wupdate(CSL_window);
  1748. wflush();
  1749. }
  1750. static clock_t prev_clock = 0;
  1751. void accept_tick(void)
  1752. {
  1753. clock_t c0 = clock();
  1754. remove_ticker();
  1755. if (c0 > prev_clock + CLOCKS_PER_SEC) {
  1756. /*
  1757. * Time spent doing all of this is counted as "overhead" or "system time"
  1758. * and not included in the times that I will report to my users...
  1759. */
  1760. if (clock_stack == &consolidated_time[0]) {
  1761. consolidated_time[0] +=
  1762. ((double)(clock_t)(c0 - base_time))/((double)CLOCKS_PER_SEC);
  1763. base_time = clock();
  1764. }
  1765. report_time((int)(100.0*consolidated_time[0]), (int)(100.0*gc_time));
  1766. }
  1767. push_clock();
  1768. wupdate(CSL_window);
  1769. poll_for_attn();
  1770. polltick_pending = NO;
  1771. ensure_screen();
  1772. add_ticker();
  1773. pop_clock();
  1774. return;
  1775. }
  1776. static char time_string[32], space_string[32];
  1777. void report_time(int32 t, int32 gct)
  1778. {
  1779. sprintf(time_string, "%d.%.2d secs", t/100, t%100);
  1780. wmenusetitem(adminmenu, MMTime, time_string);
  1781. sprintf(time_string, "+ %d.%.2d secs", gct/100, gct%100);
  1782. wmenusetitem(adminmenu, MMOTime, time_string);
  1783. }
  1784. void report_space(int gc_count, double percent)
  1785. {
  1786. sprintf(space_string, "[GC %d]:%.2f%%", gc_count, percent);
  1787. wmenusetitem(adminmenu, MMSpace, space_string);
  1788. }
  1789. void pause_for_user(void)
  1790. /*
  1791. * This is called at the end of a run so that the user gets a chance to read
  1792. * the final screen-full of output. It pops up a dialog box that will
  1793. * wait for a button push. I take the view that if output is going to a
  1794. * file then the delay is not needed, since the user can always check for
  1795. * messages there. This has the effect that non-interactive build sequences
  1796. * will often run without the pause - a good thing! Note however that this
  1797. * mean that you MUST use the close box to exit from a wimp session. Just
  1798. * "quit;" or "(stop 0)" will not do.
  1799. */
  1800. {
  1801. remove_ticker();
  1802. ensure_screen();
  1803. CSL_ew->saved = TRUE; /* Fake it */
  1804. if (spool_file != NULL) return;
  1805. /*
  1806. * Here I just loop handling events until the user hits the CLOSE box
  1807. * on my window.
  1808. */
  1809. wmessage("Leaving Reduce 3.6");
  1810. ewclose(CSL_ew);
  1811. wdone();
  1812. }
  1813. int wimpget(char *tty_buffer)
  1814. /*
  1815. * This is the main call from the body of CSL into the window manager
  1816. * to obtain input from the user. It is expected to copy some input
  1817. * characters into tty_buffer and return the number of characters
  1818. * provided. In this implementation I read the text back from the
  1819. * stdwin textedit buffer, looking rather too low.
  1820. * Any type ahead is handled in here.
  1821. */
  1822. {
  1823. TEXTEDIT* tp = CSL_ew->tp;
  1824. int i;
  1825. int n;
  1826. int lineno;
  1827. tty_nnl = 1; /* Offset from nlines */
  1828. push_clock();
  1829. remove_ticker();
  1830. if (stdout_n != 0) flush_screen();
  1831. wmenuattach(CSL_window, loadmenu);
  1832. wmenuattach(CSL_window, libmenu);
  1833. wmenuattach(CSL_window, switchmenu);
  1834. lineno = tp->nlines-1; /* Need to do this after the toend */
  1835. tty_offset = tp->foc - tp->start[lineno];
  1836. if (tty_offset<0) tty_offset += tp->gaplen;
  1837. wmenuenable(adminmenu, MMPause, NO);
  1838. if(tty_index>0) {
  1839. int i = 0;
  1840. for (; i<tty_index; i++)
  1841. if (tty_buff[i] == '\n') tty_nnl++;
  1842. tty_buff[tty_index] = '\0';
  1843. ewreplace(CSL_ew, tty_buff);
  1844. tty_index = 0;
  1845. }
  1846. event_loop();
  1847. /* fprintf(stderr, "Event loop ended\n"); */
  1848. lineno = tp->nlines-tty_nnl;
  1849. /* printf("Offset=%d Length=%d\n",tty_offset,tp->foc-tp->start[lineno]-tty_offset); */
  1850. /* for (i=0; i<tp->foc- tp->start[lineno]-tty_offset; i++) { */
  1851. /* printf("%c", *(tegettext(tp)+tp->start[lineno]+tty_offset+i)); */
  1852. /* } */
  1853. /* printf("\n"); */
  1854. memcpy(tty_buffer, tegettext(tp)+tp->start[lineno]+tty_offset,
  1855. tp->foc- tp->start[lineno]-tty_offset);
  1856. wmenudetach(CSL_window, loadmenu);
  1857. wmenudetach(CSL_window, libmenu);
  1858. wmenudetach(CSL_window, switchmenu);
  1859. wmenuenable(adminmenu, MMPause, YES);
  1860. add_ticker();
  1861. n = tp->foc- tp->start[lineno]-tty_offset;
  1862. if (n<0) {
  1863. n += tp->gaplen;
  1864. fprintf(stderr, "N correction\n");
  1865. }
  1866. tty_ready = NO;
  1867. pop_clock();
  1868. return n;
  1869. }
  1870. int char_cnt = 0;
  1871. void putc_stdout(int c)
  1872. {
  1873. *stdout_p++ = c;
  1874. *stdout_p = 0;
  1875. stdout_n++;
  1876. char_cnt++;
  1877. remove_ticker();
  1878. if (c == '\n' || stdout_n > STDOUT_BUFSIZE - LONGEST_PRINTF) {
  1879. push_clock(); flush_screen();
  1880. if (char_cnt>200) { /* Where 200 is a random number */
  1881. poll_for_attn(); char_cnt = 0;
  1882. }
  1883. pop_clock();
  1884. }
  1885. add_ticker();
  1886. }
  1887. void vfprintf_stdout(char *fmt, va_list a)
  1888. {
  1889. int n;
  1890. /*
  1891. * I have given myself LONGEST_PRINTF locations in the array for
  1892. * this vsprintf to fill in. If it overflows I am in big trouble!
  1893. */
  1894. n = vsprintf(stdout_p, fmt, a);
  1895. stdout_p += n;
  1896. stdout_n += n;
  1897. char_cnt += n;
  1898. remove_ticker();
  1899. if (stdout_n > STDOUT_BUFSIZE - LONGEST_PRINTF) {
  1900. push_clock(); flush_screen();
  1901. if (char_cnt>200) {
  1902. poll_for_attn(); char_cnt = 0;
  1903. }
  1904. pop_clock();
  1905. }
  1906. add_ticker();
  1907. }
  1908. /* end of sysxwin.c */