sysarm.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406
  1. /* sysarm.c Copyright (C) 1989-93 Codemist Ltd */
  2. /*
  3. * Acorn Archimedes-specific code
  4. */
  5. #error this version is no longer supported. The file is left in case
  6. it ever proves a useful prototype for anything else.
  7. /*
  8. * This code may be used and modified, and redistributed in binary
  9. * or source form, subject to the "CCL Public License", which should
  10. * accompany it. This license is a variant on the BSD license, and thus
  11. * permits use of code derived from this in either open and commercial
  12. * projects: but it does require that updates to this code be made
  13. * available back to the originators of the package.
  14. * Before merging other code in with this or linking this code
  15. * with other packages or libraries please check that the license terms
  16. * of the other material are compatible with those of this.
  17. */
  18. /* Signature: 3896bf7e 08-Apr-2002 */
  19. #include <stdarg.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include "bbc.h"
  23. #include "akbd.h"
  24. #include "flex.h"
  25. #include "os.h"
  26. #include "wimp.h"
  27. #include "wimpt.h"
  28. #include "werr.h"
  29. #include "win.h"
  30. #include "menu.h"
  31. #define template acorn_template /* To avoid clash with C++ */
  32. #include "template.h"
  33. #include "dbox.h"
  34. #include "txt.h"
  35. #include "saveas.h"
  36. #include "event.h"
  37. #include "res.h"
  38. #include "resspr.h"
  39. #include "baricon.h"
  40. #include "colourtran.h"
  41. #include "xferrecv.h"
  42. #include "xfersend.h"
  43. #include "sprite.h"
  44. #include "msgs.h"
  45. /* #include <swis.h> */
  46. #define Wimp_SendMessage 0x0400e7
  47. #define OS_EvaluateExpression 0x00002d
  48. #define OS_Claim 0x00001f
  49. #define OS_Release 0x000020
  50. #define OS_DelinkApplication 0x00004d
  51. #define OS_RelinkApplication 0x00004e
  52. #define Hourglass_On 0x0406c0
  53. #define Hourglass_Off 0x0406c1
  54. #define Wimp_ReadSysInfo 0x0400f2
  55. #include "machine.h"
  56. #include "version.h"
  57. #include "tags.h"
  58. #include "cslerror.h"
  59. #include "externs.h"
  60. #include "arith.h"
  61. #include "read.h"
  62. #include "entries.h"
  63. #ifdef TIMEOUT
  64. #include "timeout.h"
  65. #endif
  66. static void get_home_directory(char *b, int length);
  67. static void get_users_home_directory(char *b, int length);
  68. #include "filename.c"
  69. int create_directory(char *filename, char *old, size_t n)
  70. {
  71. process_file_name(filename, old, n);
  72. if (*filename == 0) return 1;
  73. return mkdir(filename);
  74. }
  75. int delete_file(char *filename, char *old, size_t n)
  76. {
  77. process_file_name(filename, old, n);
  78. if (*filename == 0) return NULL;
  79. return remove(filename);
  80. }
  81. CSLbool file_exists(char *filename, char *old, size_t n, char *tt)
  82. {
  83. os_filestr b;
  84. time_t t;
  85. unsigned int load, exec, w;
  86. process_file_name(filename, old, n);
  87. if (*filename == 0) return NO;
  88. b.action = 5;
  89. b.name = filename;
  90. if (os_file(&b) != 0) return NO;
  91. load = b.loadaddr; exec = b.execaddr;
  92. if ((load & 0xfff00000) != 0xfff00000) return NO;
  93. load = load & 0xff;
  94. /* Now I need to divide the datestamp by 100 */
  95. w = (load << 16) | ((exec >> 16) & 0xffff);
  96. exec = (exec & 0xffff) | ((w % 100) << 16);
  97. w = w / 100;
  98. t = (w << 16) | (exec / 100);
  99. strcpy(tt, ctime(&t));
  100. return YES;
  101. }
  102. /*
  103. * This is a dummy definition of get_truename, here so that everything
  104. * will link. Both the calling convention used here and the exact
  105. * meaning and implementation may be under gentle review!
  106. */
  107. char *get_truename(char *filename, char *old, size_t n)
  108. {
  109. char *w;
  110. process_file_name(filename, old, n);
  111. if (*filename == 0)
  112. { aerror("truename");
  113. return NULL;
  114. }
  115. w = (char *)(*malloc_hook)(1+strlen(filename));
  116. if (w == NULL) return w;
  117. strcpy(w, filename);
  118. return w;
  119. }
  120. char *my_getenv(char *s)
  121. {
  122. return getenv(s);
  123. }
  124. static void delink(void), relink(void);
  125. int my_system(char *s)
  126. {
  127. int w;
  128. delink();
  129. w = system(s);
  130. relink();
  131. return w;
  132. }
  133. /*
  134. * RISCOS does not support the idea of home directories for
  135. * users, so in case anybody still wants to use the notation "~" that
  136. * would indicate a home directory under Unix I implement something
  137. * in terms of environment variables.
  138. */
  139. static void get_home_directory(char *b, int length)
  140. {
  141. char *w = my_getenv("home");
  142. if (w != NULL) strcpy(b, w);
  143. else
  144. strcpy(b, "@");
  145. }
  146. static void get_users_home_directory(char *b, int length)
  147. {
  148. char *w, h[LONGEST_LEGAL_FILENAME];
  149. sprintf(h, "home$%s", b);
  150. w = my_getenv(h);
  151. if (w != NULL) strcpy(b, w);
  152. else
  153. strcpy(b, "@");
  154. }
  155. /*
  156. * The following structure MUST match the layout of a FILE as used by
  157. * the library that is linked with.
  158. */
  159. #define FILEHANDLE int
  160. struct FILE_COPY
  161. { int icnt; /* two separate _cnt fields so we can police ... */
  162. unsigned char *ptr;
  163. int ocnt; /* ... restrictions that read/write are fseek separated */
  164. int flag;
  165. unsigned char *base; /* buffer base */
  166. int file; /* RISCOS/Arthur/Brazil file handle */
  167. long pos; /* position in file */
  168. int bufsiz; /* maximum buffer size */
  169. int signature; /* used with temporary files */
  170. unsigned char lilbuf[2]; /* single byte buffer for them that want it */
  171. /* plus an unget char is put in __lilbuf[1] */
  172. long lspos; /* what __pos should be (set after lazy seek)*/
  173. unsigned char *extent; /* extent of writes into the current buffer */
  174. int buflim; /* used size of buffer */
  175. int icnt_save; /* after unget contains old icnt */
  176. int ocnt_save; /* after unget contains old ocnt */
  177. };
  178. static int pipe_ptr = 0;
  179. static unsigned char pipe_buffer[20+256];
  180. static CSLbool under_wimp = NO;
  181. FILE *my_popen(char *cmd, char *dirn)
  182. {
  183. if (!under_wimp) return NULL;
  184. pipe_ptr = 20;
  185. return (FILE *)1;
  186. }
  187. void my_pipe_putc(int c, FILE *f)
  188. {
  189. if (pipe_ptr >= 20 && pipe_ptr < sizeof(pipe_buffer)-1)
  190. { if (c == '\n') my_pipe_flush(f);
  191. else pipe_buffer[pipe_ptr++] = c;
  192. }
  193. }
  194. void my_pipe_flush(FILE *f)
  195. {
  196. if (pipe_ptr > 20 && pipe_ptr < sizeof(pipe_buffer)-1)
  197. { int32 *w = (int32 *)pipe_buffer;
  198. remove_ticker();
  199. delink();
  200. pipe_buffer[pipe_ptr] = 0;
  201. w[0] = (pipe_ptr + 4) & ~3;
  202. w[1] = 0;
  203. w[2] = 0;
  204. w[3] = 0; /* An original message, this one */
  205. w[4] = 0x0c1202; /* A magic number for GNUPLOT, I am told! */
  206. os_swi3(Wimp_SendMessage, 17, (int)w, 0);
  207. relink();
  208. add_ticker();
  209. /* here w[2] is my reference for the message */
  210. accept_tick();
  211. }
  212. pipe_ptr = 20;
  213. return;
  214. }
  215. void my_pclose(FILE *f)
  216. {
  217. return;
  218. }
  219. int batchp()
  220. {
  221. return (((struct FILE_COPY *)stdin)->file != 0);
  222. }
  223. /*
  224. * The following function controls memory allocation policy
  225. */
  226. int32 ok_to_grab_memory(int32 current)
  227. {
  228. return 3*current + 2;
  229. }
  230. /*
  231. * The next procedure is responsible for establishing information about
  232. * where the main checkpoint image should be recovered from, and where
  233. * and fasl files should come from.
  234. */
  235. static char appname[16] = "!CSL";
  236. static char CSL_version_string[64];
  237. static char LOADSTART[16] = "(rdf \"";
  238. static char LOADEND[16] = "\")";
  239. char *find_image_directory(int argc, char *argv[])
  240. {
  241. char image[LONGEST_LEGAL_FILENAME];
  242. char pgmname[LONGEST_LEGAL_FILENAME];
  243. char *w;
  244. CSLbool riscos_application = NO;
  245. int i;
  246. /*
  247. * For RISCOS there are a number of possibilities that can support
  248. * either window-launched uses or command-line driven uses of this code.
  249. *
  250. * When launched from the window manager I will be called with a full
  251. * path name for by executable binary available in argv[0], and this will
  252. * always be of the form xxx.yyy.!zzz.!runimage
  253. * In this case I will use
  254. * xxx.yyy.!zzz.-runimage
  255. * as the name for my checkpoint file, and I will treate zzz as the name
  256. * of the application, using that name to control what appears in menus
  257. * and what sprites I use to display things.
  258. *
  259. * The second possibility is that I am called from a command-line. In that
  260. * case if the command line request was of the form
  261. * !zzz.!qqq
  262. * then I view zzz as the application name, and use !zzz.-qqq as the
  263. * checkpoint file. The use of things like xxx.yyy.!zzz.!qqq will be
  264. * supported in this case too.
  265. *
  266. * A final strategy is used if the command line shows only one component
  267. * of a file name, or if either of the two final components in the path
  268. * fail to start with '!'. In this case if the final component of the
  269. * name (i.e. of argv[0]) is xxx or !xxx then I look up the value of a shell
  270. * variable xxx$dir, and if look for a file called "-runimage" in that
  271. * directory. If argv[0] is null I take it to be "csl" and if the
  272. * environment variable indicated here is unset I look for -runimage in
  273. * the current directory. In such cases the application name is taken as xxx.
  274. */
  275. if (argc > 0 && argv[0] != NULL)
  276. { int j, r0, r1;
  277. w = argv[0];
  278. sprintf(pgmname, "\"%s\"\n", w);
  279. /*
  280. * The following line expands any shell-variables mentioned in the
  281. * command that launched me. E.g. typically from the window manager
  282. * the raw command-line will have been
  283. * <Obey$Dir>.!RunImage ...
  284. * and I need to expand <Obey$Dir>
  285. */
  286. os_swi3r(OS_EvaluateExpression,
  287. (int)pgmname, (int)image, LONGEST_LEGAL_FILENAME,
  288. &r0, &r1, &i);
  289. if (r1 == 0) sprintf(image, "%d", i);
  290. else image[i] = 0;
  291. w = image;
  292. i = strlen(w);
  293. while (i > 0 && w[i-1] != '.') i--;
  294. j = i-1;
  295. while (j > 0 && w[j-1] != '.') j--;
  296. if (j >= 0 && w[i] == '!' && w[j] == '!')
  297. { w[i] = '-';
  298. if (i > j+16) i = j+16; /* Truncate name if necessary */
  299. sprintf(appname, "%.*s", i-j-1, &w[j]);
  300. riscos_application = YES;
  301. }
  302. else
  303. { strcpy(pgmname, &w[i]);
  304. strcpy(image, pgmname);
  305. }
  306. }
  307. else strcpy(image, "!csl"); /* even argv[0] is not available! */
  308. if (!riscos_application)
  309. {
  310. /*
  311. * If I get here then image contains the final component of the application
  312. * name, and I must use it to build the name of an environment variable to
  313. * check.
  314. */
  315. if (image[0] == '!')
  316. { sprintf(pgmname, "%s$dir", &image[1]);
  317. sprintf(appname, "%.15s", image);
  318. }
  319. else
  320. { sprintf(pgmname, "%s$dir", image);
  321. sprintf(appname, "!%.15s", image);
  322. }
  323. w = my_getenv(pgmname);
  324. if (w == NULL) w = "@";
  325. sprintf(image, "%s.-runimage", w);
  326. }
  327. w = appname; /* Force application name into upper case */
  328. while ((i = *w) != 0)
  329. { if (islower(i)) i = toupper(i);
  330. *w++ = i;
  331. }
  332. if (strcmp(appname, "!CSL") != 0)
  333. { strcpy(LOADSTART, "in \"");
  334. strcpy(LOADEND, "\";");
  335. }
  336. /*
  337. * I copy from local vectors into malloc'd space to hand my
  338. * answer back.
  339. */
  340. w = (char *)(*malloc_hook)(1+strlen(image));
  341. /*
  342. * The error exit here seem unsatisfactory...
  343. */
  344. if (w == NULL)
  345. { fprintf(stderr, "\n+++ Panic - run out of space\n");
  346. exit(EXIT_FAILURE);
  347. }
  348. strcpy(w, image);
  349. sprintf(CSL_version_string, "%s %s (%s)", appname+1, VERSION, __DATE__);
  350. return w;
  351. }
  352. #ifdef PROFILED
  353. /*
  354. * The following are really part of the ARM C library, but are included here
  355. * first as prototypes in case the ideas are useful with other architectures.
  356. *
  357. * Support for gathering various sorts of information that shows where time
  358. * may be going in this system. Un Unix machines try prof/monitor and friends.
  359. */
  360. extern void *__RO_Base, *__RO_Limit;
  361. extern void _count(void);
  362. extern void _count1(void);
  363. typedef union count_position
  364. /*
  365. * This defines the format of the word that follows on from a call
  366. * to _count1(). The related constant values are related to the way that
  367. * file-name decoding tables are packed away.
  368. */
  369. {
  370. int i;
  371. struct s
  372. { unsigned int posn:12,
  373. line:16,
  374. file:4;
  375. } s;
  376. } count_position;
  377. #define file_name_map_start 0xfff12340 /* Magic number */
  378. #define file_name_map_end 0x31415926 /* Magic number */
  379. #define word_roundup(s) ((char *)(((int)s + 3) & (~3)))
  380. static char *find_file_map(int p)
  381. {
  382. int i, w;
  383. char *s;
  384. while (((w = *(int *)p) & 0xfffffff0) != file_name_map_start)
  385. { if (p >= (int)__RO_Limit) return "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  386. p += 4;
  387. }
  388. s = (char *)(p + 4);
  389. for ( i = 0; i<=(w & 0xf); i++)
  390. { s += 1 + strlen(s);
  391. s = word_roundup(s);
  392. }
  393. if (*(int *)s != file_name_map_end) return find_file_map((int)s);
  394. return (char *)(p + 4);
  395. }
  396. void show_counts(void)
  397. {
  398. int count = (int)_count; /* address of the function as an int */
  399. int p, onthisline = 0, w1 = 0, w2 = 0;
  400. myprintf("\nCounts from %p to %p\n", __RO_Base, __RO_Limit);
  401. for (p = (int)__RO_Base; p<(int)__RO_Limit; p += 4)
  402. { int w = *(int *)p;
  403. if ((w & 0xff000000) == 0xeb000000) /* Unconditional BL instruction */
  404. { int dest = (p + 8 + 4*(w & 0x00ffffff)) & 0x03fffffc;
  405. if (dest == count)
  406. { myprintf("%.6x: %-10u ", p, *(int *)(p + 4));
  407. if (onthisline == 3) onthisline = 0, myprintf("\n");
  408. else onthisline++, myprintf(" ");
  409. }
  410. }
  411. if ((w & 0xfffe0000) == 0xe92c0000 && /* STMFD sp!, sp = r12 or r13 */
  412. w1 == 0xe1a0b00c && /* MOV ip, sp @@@@@ */
  413. (w2 & 0xffff0000) == 0xff000000)
  414. { char *name = (char *)(p - 8 - (w2 & 0xffff));
  415. int len = 0;
  416. char *temp = name;
  417. /* I do not use strlen() here to keep the library more modular */
  418. while (*temp++ != 0) len++;
  419. if (len >= 10 && onthisline == 3)
  420. { onthisline = 0;
  421. myprintf("\n");
  422. }
  423. myprintf( "%.6x: %s", p - 4, name);
  424. len = 11 - strlen(name);
  425. while (len < 0) len += 20, onthisline++;
  426. while (len > 0) len--, myprintf(" ");
  427. if (onthisline >= 3) onthisline = 0, myprintf("\n");
  428. else onthisline++, myprintf(" ");
  429. }
  430. w2 = w1;
  431. w1 = w;
  432. }
  433. if (onthisline != 0) myprintf(" ");
  434. }
  435. void write_profile(char *filename)
  436. {
  437. /* Create a (binary) file containing execution profile information for */
  438. /* the current program. The format is eccentric, and must be kept in step */
  439. /* with (a) parts of armgen.c that generate code that collects statistics */
  440. /* and (b) code in misc.c that reads in the binary file created here and */
  441. /* displays the counts attached to a source listing of the original code. */
  442. int count1 = (int)_count1;
  443. int p, w1 = 0, w2 = 0, pass, nfiles = 0, namebytes = 0, ncounts = 0;
  444. int global_name_offset[256];
  445. char *global_file_map[256]; /* Limits total number of files allowed */
  446. FILE *map_file = fopen(filename, "wb");
  447. char *file_map;
  448. if (map_file == NULL)
  449. { myprintf("\nUnable to open %s for execution profile log\n",
  450. filename);
  451. return;
  452. }
  453. for (pass = 1; pass <=2; pass++)
  454. {
  455. if (pass == 2)
  456. /* Write file header indicating size of sub-parts */
  457. { fwrite("\xff*COUNTFILE*", 4, 3, map_file);
  458. fwrite(&namebytes, 4, 1, map_file);
  459. fwrite(&nfiles, 4, 1, map_file);
  460. fwrite(&ncounts, 4, 1, map_file);
  461. for (p = 0; p < nfiles; p++)
  462. { char *ss = global_file_map[p];
  463. int len = 1 + strlen(ss);
  464. len = ((len + 3) & (~3)) / 4;
  465. fwrite(ss, 4, len, map_file);
  466. }
  467. for (p = 0; p < nfiles; p++)
  468. fwrite(&global_name_offset[p], 4, 1, map_file);
  469. }
  470. file_map = NULL;
  471. for (p = (int)__RO_Base; p<(int)__RO_Limit; p += 4)
  472. { int w = *(int *)p;
  473. if ((w & 0xff000000) == 0xeb000000) /* BL instruction */
  474. { int dest = (p + 8 + 4*(w & 0x00ffffff)) & 0x03fffffc;
  475. if (dest == count1)
  476. { count_position k;
  477. int i;
  478. char *s;
  479. if (file_map == NULL ||
  480. (int)file_map <= p) file_map = find_file_map(p+12);
  481. s = file_map;
  482. k.i = *(int *)(p + 8);
  483. for (i = 0; i<k.s.file; i++)
  484. { s += 1 + strlen(s);
  485. s = word_roundup(s);
  486. }
  487. if (pass == 1)
  488. { int i;
  489. for (i = 0;;i++)
  490. { if (i >= nfiles)
  491. { global_name_offset[nfiles] = namebytes;
  492. global_file_map[nfiles++] = s;
  493. namebytes += 1 + strlen(s);
  494. namebytes = (namebytes + 3) & (~3);
  495. break;
  496. }
  497. else if (strcmp(s,global_file_map[i]) ==0) break;
  498. }
  499. ncounts++;
  500. }
  501. else
  502. { int i;
  503. for (i = 0; strcmp(s, global_file_map[i]) !=0; i++);
  504. fwrite((int *)(p + 4), 4, 1, map_file);
  505. i = (k.s.line & 0xffff) | (i << 16);
  506. fwrite(&i, 4, 1, map_file);
  507. }
  508. p += 8;
  509. }
  510. }
  511. w2 = w1;
  512. w1 = w;
  513. }
  514. }
  515. fwrite("\xff*ENDCOUNT*\n", 4, 3, map_file); /* Trailer data */
  516. fclose(map_file);
  517. myprintf("\nProfile information written to %s\n", filename);
  518. }
  519. #endif /* PROFILED */
  520. /*
  521. * Wimp interfaces...
  522. */
  523. static CSLbool CSL_window_open = NO;
  524. static menu Iconbar_menu = 0, Main_menu = 0;
  525. static txt session;
  526. static txt_marker session_marker;
  527. #define MInfo 1 /* Icon-bar menu items */
  528. #define MQuit 2
  529. #define Vfield 4 /* version number field in "about" box */
  530. #define MMInt 1 /* main window menu items */
  531. #define MMAbort 2
  532. #define MMQuit 3
  533. #define MMSave 4
  534. #define MMSelAll 5
  535. #define MMCopy 6
  536. #define MMDelete 7
  537. #define MMClear 8
  538. #define BUFLEN 256
  539. /*
  540. * Text window event handling
  541. */
  542. static char *clipboard = NULL;
  543. static int clipboard_size = 0, clipboard_p, clipboard_n;
  544. typedef enum wimp_source_t
  545. {
  546. from_keyboard = 0,
  547. from_clipboard,
  548. from_file
  549. } wimp_source_t;
  550. static wimp_source_t wimp_source = from_keyboard;
  551. #define TTYBUF_SIZE 256
  552. static CSLbool tty_ready = NO;
  553. static int tty_icount = 0;
  554. static char tty_ibuffer[TTYBUF_SIZE];
  555. #ifdef TICK_STREAM
  556. extern void wimp_tick(void);
  557. /*
  558. * wimp_tick behaves roughly as shown in the following code, but is
  559. * in assembly code (in asmarm.s) since it is an interrupt routine and I
  560. * am required to adhere to rigid register-use etc conventions...
  561. *
  562. * void wimp_tick()
  563. * {
  564. * polltick_pending = YES;
  565. * if (tick_pending) return;
  566. * else if (already_in_gc) tick_on_gc_exit = YES;
  567. * else
  568. * { Lisp_Object nil = C_nil;
  569. * tick_pending = YES;
  570. * saveheaplimit = heaplimit;
  571. * heaplimit = fringe;
  572. * savevheaplimit = vheaplimit;
  573. * vheaplimit = vfringe;
  574. * savecodelimit = codelimit;
  575. * codelimit = codefringe;
  576. * savestacklimit = stacklimit;
  577. * stacklimit = stackbase;
  578. * }
  579. * return;
  580. * }
  581. */
  582. static CSLbool ticker_active = NO;
  583. void remove_ticker()
  584. {
  585. if (!ticker_active) return;
  586. #ifndef SOFTWARE_TICKS
  587. os_swi3(OS_Release, 0x1c, (int)wimp_tick, 0x91494530);
  588. #endif
  589. ticker_active = NO;
  590. }
  591. void add_ticker()
  592. {
  593. if (ticker_active) return;
  594. #ifdef SOFTWARE_TICKS
  595. countdown = SOFTWARE_TICKS;
  596. #else
  597. os_swi3(OS_Claim, 0x1c, (int)wimp_tick, 0x91494530);
  598. #endif
  599. ticker_active = YES;
  600. }
  601. #endif /* TICK_STREAM */
  602. static char task_links[61];
  603. static void delink()
  604. {
  605. os_swi2(OS_DelinkApplication, (int)&task_links[0], sizeof(task_links));
  606. }
  607. static void relink()
  608. {
  609. os_swi1(OS_RelinkApplication, (int)&task_links[0]);
  610. }
  611. static int selstart = -1, selend = -1, dragstart = -1;
  612. static int done_something = 0;
  613. static BOOL enlarge_clipboard(char **bufp, int *lenp)
  614. {
  615. if (!flex_extend((flex_ptr)&clipboard, clipboard_size+128))
  616. return FALSE;
  617. clipboard_size += 128;
  618. *bufp = clipboard;
  619. *lenp = clipboard_size;
  620. return TRUE;
  621. }
  622. static void clip_selection()
  623. {
  624. int p1 = txt_selectstart(session), p2 = txt_selectend(session), i;
  625. clipboard_p = clipboard_n = 0;
  626. wimp_source = from_clipboard;
  627. for (i=p1; i<p2; i++)
  628. { int c = txt_charat(session, i);
  629. if (clipboard_n >= clipboard_size)
  630. { if (!flex_extend((flex_ptr)&clipboard, clipboard_size+128)) return;
  631. clipboard_size += 128;
  632. }
  633. clipboard[clipboard_n++] = c;
  634. }
  635. }
  636. static void CSL_txthandler(txt t, void *handle)
  637. {
  638. txt_eventcode e;
  639. CSL_IGNORE(t); /* I only have one txt, so I use its global handle */
  640. CSL_IGNORE(handle);
  641. e = txt_get(session);
  642. /*
  643. * An event is either a mouse one or it involves the keyboard.
  644. * The latter is taken to include all sorts of special cases such as
  645. * hits on various buttons.
  646. * For mouse hits I need to support region selection as well as just
  647. * positioning.
  648. */
  649. if (e & txt_MOUSECODE)
  650. { int mousepos = e & 0xffffff;
  651. if (mousepos == 0xffffff) return;
  652. if (e & txt_MSELECT)
  653. { txt_setdot(session, mousepos);
  654. if ((e & txt_MSELOLD) && (dragstart >= 0))
  655. { if (mousepos >= dragstart)
  656. selstart = dragstart, selend = mousepos;
  657. else selstart = mousepos, selend = dragstart;
  658. wimp_source = from_keyboard;
  659. }
  660. else dragstart = mousepos;
  661. }
  662. else if ((e & txt_MSELOLD) && (dragstart >= 0))
  663. { if (mousepos >= dragstart)
  664. selstart = dragstart, selend = mousepos;
  665. else selstart = mousepos, selend = dragstart;
  666. dragstart = -1;
  667. wimp_source = from_keyboard;
  668. }
  669. else if ((e & txt_MEXTEND) && (selstart >= 0))
  670. { if (2*mousepos <= (selstart+selend)) selstart = mousepos;
  671. else selend = mousepos;
  672. wimp_source = from_keyboard;
  673. }
  674. if (selstart != selend) txt_setselect(session, selstart, selend);
  675. else txt_setselect(session, 0, 0); /* Unset any selection */
  676. done_something = 1;
  677. }
  678. else switch(e)
  679. {
  680. case txt_EXTRACODE + akbd_Sh + akbd_Ctl + akbd_UpK: /* Scroll up one line */
  681. txt_movevertical(session, -1, 1);
  682. break;
  683. case txt_EXTRACODE + akbd_Sh + akbd_UpK: /* Scroll up one page */
  684. txt_movevertical(session, -txt_visiblelinecount(session), 1);
  685. break;
  686. case txt_EXTRACODE + akbd_Sh + akbd_Ctl + akbd_DownK: /* Down one line */
  687. txt_movevertical(session, 1, 1);
  688. break;
  689. case txt_EXTRACODE + akbd_Sh + akbd_DownK: /* Down one page */
  690. txt_movevertical(session, txt_visiblelinecount(session), 1);
  691. break;
  692. case akbd_LeftK: /* left arrow key */
  693. txt_movehorizontal(session, -1);
  694. break;
  695. case akbd_RightK: /* right arrow key */
  696. txt_movehorizontal(session, 1);
  697. break;
  698. case akbd_UpK: /* up arrow key */
  699. txt_movevertical(session, -1, 0);
  700. break;
  701. case akbd_DownK: /* down arrow key */
  702. txt_movevertical(session, 1, 0);
  703. break;
  704. case txt_EXTRACODE + akbd_Fn +akbd_Sh + 2: /* Insert drag file */
  705. { char *filename;
  706. int filetype, len;
  707. if ((filetype = xferrecv_checkinsert(&filename)) != -1)
  708. { len = strlen(LOADSTART) + strlen(filename) + strlen(LOADEND);
  709. if (tty_icount + len < TTYBUF_SIZE)
  710. { sprintf(&tty_ibuffer[tty_icount], "%s%s%s",
  711. LOADSTART, filename, LOADEND);
  712. tty_icount += len;
  713. txt_setdot(session, txt_size(session));
  714. txt_insertstring(session, LOADSTART);
  715. txt_setdot(session, txt_size(session));
  716. txt_insertstring(session, filename);
  717. txt_setdot(session, txt_size(session));
  718. txt_insertstring(session, LOADEND);
  719. txt_setdot(session, txt_size(session));
  720. }
  721. xferrecv_insertfileok();
  722. }
  723. else if ((filetype = xferrecv_checkimport(&len)) != -1)
  724. { clipboard_p = 0;
  725. clipboard_n = xferrecv_doimport(clipboard, clipboard_size,
  726. enlarge_clipboard);
  727. xferrecv_insertfileok();
  728. if (clipboard_n > 0) wimp_source = from_clipboard;
  729. txt_setdot(session, txt_size(session));
  730. }
  731. }
  732. break;
  733. case txt_EXTRACODE + akbd_Fn + 127: /* close icon */
  734. case akbd_Fn + akbd_Ctl + 2: /* Ctl-F2 also quits */
  735. txt_dispose(&session);
  736. exit(0);
  737. break;
  738. case 127: /* backspace and ^H */
  739. case 8:
  740. txt_setdot(session, txt_size(session));
  741. txt_movehorizontal(session, -1);
  742. txt_delete(session, 1);
  743. if (tty_icount > 0) tty_icount--;
  744. break;
  745. default:
  746. if (e & txt_EXTRACODE)
  747. { sprintf(&tty_ibuffer[tty_icount], "<%.8x>", e);
  748. tty_ibuffer[tty_icount+10] = 0;
  749. txt_setdot(session, txt_size(session));
  750. txt_insertstring(session, &tty_ibuffer[tty_icount]);
  751. txt_setdot(session, txt_size(session));
  752. tty_icount += 10;
  753. }
  754. else if (e >= 256) wimp_processkey(e); /* give back to wimp */
  755. else switch (e)
  756. {
  757. case 'C' & 0x1f: /* ^C = copy selection */
  758. if (selstart == selend || selstart < 0) break;
  759. clip_selection();
  760. break;
  761. case 'X' & 0x1f: /* ^X = delete selection */
  762. if (selstart == selend || selstart < 0) break;
  763. txt_movemarker(session, &session_marker, txt_dot(session));
  764. txt_setdot(session, txt_selectstart(session));
  765. txt_delete(session, txt_selectend(session)-txt_selectstart(session));
  766. txt_movedottomarker(session, &session_marker);
  767. wimp_source = from_keyboard;
  768. break;
  769. case 'Z' & 0x1f: /* ^Z = cancel selection */
  770. selstart = selend = -1;
  771. txt_setselect(session, 0, 0); /* Unset any selection */
  772. wimp_source = from_keyboard;
  773. break;
  774. default:
  775. if (e == 4 || e == 13 ||
  776. e == 7 || e == 0x1b || /* bell and <escape> */
  777. e >= 32 && e < 127)
  778. {
  779. if (e == 13) e = 10; /* newline char is special case */
  780. txt_setdot(session, txt_size(session));
  781. txt_insertchar(session, e); /* insert the char */
  782. txt_movedot(session, 1); /* advance the dot */
  783. /*
  784. * I ignore characters (with no comment) if the user types in > 256
  785. * of them on one line.
  786. */
  787. if (tty_icount < TTYBUF_SIZE)
  788. { tty_ibuffer[tty_icount++] = e;
  789. if (e == 10) tty_ready = YES;
  790. }
  791. }
  792. }
  793. break;
  794. }
  795. }
  796. #define SCROLLBACK 4000
  797. #define STDOUT_BUFSIZE 1024
  798. #define LONGEST_PRINTF 120
  799. static char stdout_buffer[STDOUT_BUFSIZE];
  800. static char *stdout_p;
  801. static int stdout_n;
  802. static BOOL saveproc(char *filename, void *handle)
  803. {
  804. FILE *f = fopen(filename, "w");
  805. int i;
  806. CSL_IGNORE(handle);
  807. if (f == NULL) return FALSE;
  808. if (selstart == selend || selstart < 0) return FALSE;
  809. for (i=txt_selectstart(session); i<=txt_selectend(session); i++)
  810. putc(txt_charat(session, i), f);
  811. fclose(f);
  812. return TRUE;
  813. }
  814. static BOOL sendproc(void *handle, int *maxbuf)
  815. {
  816. int i;
  817. char buf[4];
  818. CSL_IGNORE(handle); CSL_IGNORE(maxbuf);
  819. for (i=txt_selectstart(session); i<=txt_selectend(session); i++)
  820. { buf[0] = txt_charat(session, i);
  821. if (!xfersend_sendbuf(buf, 1)) return FALSE;
  822. }
  823. return TRUE;
  824. }
  825. /*
  826. * Menu to be generated by "menu" button when mouse is over our main
  827. * text window
  828. */
  829. static void Main_menuproc(void *handle, char *hit)
  830. {
  831. CSL_IGNORE(handle);
  832. switch (hit[0])
  833. {
  834. case MMInt:
  835. #ifdef SOFTWARE_TICKS
  836. countdown = -1;
  837. #endif
  838. interrupt_pending = YES;
  839. wimp_source = from_keyboard;
  840. break;
  841. case MMAbort:
  842. #ifdef SOFTWARE_TICKS
  843. countdown = -1;
  844. #endif
  845. interrupt_pending = YES;
  846. wimp_source = from_keyboard;
  847. break;
  848. case MMQuit:
  849. exit(0);
  850. break;
  851. case MMSave:
  852. wimp_source = from_keyboard;
  853. saveas(0xfff, "savetext", txt_size(session),
  854. saveproc, sendproc, NULL, NULL);
  855. break;
  856. case MMSelAll:
  857. selstart = 0;
  858. selend = txt_size(session) - 1;
  859. if (selstart != selend) txt_setselect(session, selstart, selend);
  860. break;
  861. case MMCopy:
  862. if (selstart == selend || selstart < 0) break;
  863. clip_selection();
  864. break;
  865. case MMDelete:
  866. if (selstart == selend || selstart < 0) break;
  867. txt_movemarker(session, &session_marker, txt_dot(session));
  868. txt_setdot(session, txt_selectstart(session));
  869. txt_delete(session, txt_selectend(session)-txt_selectstart(session));
  870. txt_movedottomarker(session, &session_marker);
  871. wimp_source = from_keyboard;
  872. break;
  873. case MMClear:
  874. selstart = selend = -1;
  875. txt_setselect(session, 0, 0); /* Unset any selection */
  876. wimp_source = from_keyboard;
  877. break;
  878. }
  879. }
  880. static CSLbool CSL_create_txt(char *title)
  881. /*
  882. * returns YES if all went well
  883. */
  884. {
  885. /* Create a new txt object. The title passed here over-rides one in the
  886. template file (a bit of a pity, that?) */
  887. if ((session = txt_new(title)) == 0) return NO;
  888. txt_newmarker(session, &session_marker);
  889. clipboard_size = 128;
  890. if (!flex_alloc((flex_ptr)&clipboard, clipboard_size)) return NO;
  891. CSL_window_open = YES;
  892. if ((Main_menu = menu_new(appname+1,
  893. "Interrupt,Abort,Quit|>Save,SelectAll,Copy ^C,Delete ^X,Clear ^Z"
  894. )) == NULL)
  895. return NO;
  896. if (!event_attachmenu(txt_syshandle(session), Main_menu, Main_menuproc, 0))
  897. return NO;
  898. /* Attach an event handler for the txt */
  899. txt_eventhandler(session, CSL_txthandler, 0);
  900. /* Show the txt to the user */
  901. txt_show(session);
  902. /* Set "dot" at beginning */
  903. txt_setdot(session, 0);
  904. stdout_p = stdout_buffer;
  905. stdout_n = 0;
  906. win_claim_idle_events(txt_syshandle(session));
  907. event_setmask((wimp_emask)0); /* permits null events to show up */
  908. return YES;
  909. }
  910. /*
  911. * Icon Bar Icon.
  912. */
  913. static void CSL_clickproc(wimp_i i)
  914. {
  915. CSL_IGNORE(i);
  916. if (!CSL_window_open)
  917. { if (!CSL_create_txt(appname+1))
  918. werr(YES, "Unable to create text object - exiting");
  919. }
  920. }
  921. static void Iconbar_menuproc(void *handle, char *hit)
  922. {
  923. CSL_IGNORE(handle);
  924. switch (hit[0])
  925. {
  926. case MInfo:
  927. { dbox d;
  928. d = dbox_new("ProgInfo");
  929. if (d == 0) return;
  930. dbox_setfield(d, Vfield, CSL_version_string);
  931. dbox_show(d);
  932. dbox_fillin(d);
  933. dbox_dispose(&d);
  934. }
  935. break;
  936. case MQuit:
  937. exit(0);
  938. break;
  939. }
  940. }
  941. /*
  942. * Arrange that files can be loaded into CSL by dragging
  943. */
  944. static void CSL_load_events(wimp_eventstr *e, void *handle)
  945. {
  946. CSL_IGNORE(handle);
  947. if (e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK)
  948. {
  949. if (CSL_window_open && e->data.msg.hdr.action == wimp_MDATALOAD)
  950. { char *filename;
  951. int filetype, len;
  952. filetype = xferrecv_checkinsert(&filename);
  953. if (filetype != -1)
  954. { len = strlen(LOADSTART) + strlen(filename) + strlen(LOADEND);
  955. if (tty_icount + len < TTYBUF_SIZE)
  956. { sprintf(&tty_ibuffer[tty_icount], "%s%s%s",
  957. LOADSTART, filename, LOADEND);
  958. tty_icount += len;
  959. txt_setdot(session, txt_size(session));
  960. txt_insertstring(session, LOADSTART);
  961. txt_setdot(session, txt_size(session));
  962. txt_insertstring(session, filename);
  963. txt_setdot(session, txt_size(session));
  964. txt_insertstring(session, LOADEND);
  965. txt_setdot(session, txt_size(session));
  966. }
  967. xferrecv_insertfileok();
  968. }
  969. }
  970. }
  971. }
  972. /*
  973. * Output procedures
  974. */
  975. static clock_t last_output_time;
  976. void flush_screen()
  977. /*
  978. * Bring screen up to date
  979. */
  980. {
  981. int n;
  982. if (!under_wimp)
  983. { fflush(stdout);
  984. return;
  985. }
  986. if (stdout_n == 0)
  987. { last_output_time = clock();
  988. return;
  989. }
  990. remove_ticker();
  991. delink();
  992. n = txt_size(session);
  993. /*
  994. * This code is intended to keep about around SCROLLBACK characters
  995. * buffered for the user to scroll back to. If I have more than SCROLLBACK
  996. * stored when I come to update the display I will discard some.
  997. */
  998. if (n > SCROLLBACK)
  999. { txt_setcharoptions(session, txt_DISPLAY, (txt_charoption)0);
  1000. txt_setdot(session, 0);
  1001. txt_delete(session, SCROLLBACK - n + stdout_n);
  1002. txt_setdot(session, txt_size(session));
  1003. txt_setcharoptions(session, txt_DISPLAY, txt_DISPLAY);
  1004. n = txt_size(session);
  1005. }
  1006. if (n != txt_dot(session)) txt_setdot(session, txt_size(session));
  1007. txt_insertstring(session, stdout_buffer);
  1008. txt_setdot(session, txt_size(session));
  1009. stdout_p = stdout_buffer;
  1010. stdout_n = 0;
  1011. last_output_time = clock();
  1012. relink();
  1013. add_ticker();
  1014. }
  1015. static void remove_hourglass(void);
  1016. void pause_for_user()
  1017. /*
  1018. * This is called at the end of a run so that the user gets a chance to read
  1019. * the final screen-full of output. It pops up a dialog box that will
  1020. * wait for a button push. I take the view that if output is going to a
  1021. * file then the delay is not needed, since the user can always check for
  1022. * messages there. This has the effect that non-interactive build sequences
  1023. * will often run without the pause - a good thing! Note however that this
  1024. * mean that you MUST use the close box to exit from a wimp session. Just
  1025. * "quit;" or "(stop 0)" will not do. At least "quit;" etc pops up the
  1026. * dialog box you see here...
  1027. */
  1028. {
  1029. dbox d;
  1030. if (spool_file != NULL || !use_wimp) return;
  1031. ensure_screen();
  1032. remove_ticker();
  1033. delink();
  1034. remove_hourglass();
  1035. d = dbox_new("finished");
  1036. if (d == 0) return; /* Unable to find the "finish" dialog box */
  1037. dbox_show(d);
  1038. dbox_fillin(d);
  1039. dbox_dispose(&d);
  1040. return;
  1041. }
  1042. void putc_stdout(int c)
  1043. {
  1044. if (under_wimp)
  1045. { *stdout_p++ = c;
  1046. *stdout_p = 0;
  1047. stdout_n++;
  1048. if (stdout_n > STDOUT_BUFSIZE - LONGEST_PRINTF) ensure_screen();
  1049. if (polltick_pending) accept_tick();
  1050. }
  1051. else putchar(c);
  1052. }
  1053. static char txt_title[64];
  1054. static int last_gc_count=-1, last_t=-1, last_gct=-1;
  1055. static double last_percent;
  1056. void report_time(int32 t, int32 gct)
  1057. {
  1058. int pos;
  1059. if (!under_wimp) return;
  1060. sprintf(txt_title, "%s", appname+1);
  1061. pos = strlen(txt_title);
  1062. last_t = t;
  1063. last_gct = gct;
  1064. if (last_t != -1)
  1065. sprintf(&txt_title[pos], " time %ld.%.2ld+%ld.%.2ld secs",
  1066. last_t/100L, last_t%100L, last_gct/100L, last_gct%100L);
  1067. pos = strlen(txt_title);
  1068. if (last_gc_count != -1)
  1069. sprintf(&txt_title[pos], " GC %d [%.2f%% full]", last_gc_count, last_percent);
  1070. txt_settitle(session, txt_title);
  1071. }
  1072. void report_space(int gc_count, double percent)
  1073. {
  1074. last_gc_count = gc_count;
  1075. last_percent = percent;
  1076. report_time(last_t, last_gct);
  1077. }
  1078. /*
  1079. * Input procedures
  1080. */
  1081. static CSLbool hourglass_showing;
  1082. static void remove_hourglass()
  1083. {
  1084. if (hourglass_showing)
  1085. { os_swi0(Hourglass_Off);
  1086. hourglass_showing = NO;
  1087. }
  1088. }
  1089. int wimpget(char *tty_buffer)
  1090. /*
  1091. * This is the main call from the body of CSL into the window manager
  1092. * to obtain input from the user. It is expected to copy some input
  1093. * characters into tty_buffer and return the number of characters
  1094. * provided. In this implementation I keep a separate buffer called
  1095. * tty_ibuffer that characters are collected into - when either this
  1096. * gets full or a newline is inserted into it I copy it to tty_buffer
  1097. * and return.
  1098. * I will cancel copies from a selection if I have almost any mouse
  1099. * activity.
  1100. */
  1101. {
  1102. int n;
  1103. if (stdout_n != 0) ensure_screen();
  1104. mouse_directed_input:
  1105. switch (wimp_source)
  1106. {
  1107. case from_clipboard:
  1108. while (wimp_source == from_clipboard)
  1109. { int c = clipboard[clipboard_p++];
  1110. txt_setdot(session, txt_size(session));
  1111. txt_insertchar(session, c); /* insert the char */
  1112. txt_movedot(session, 1); /* advance the dot */
  1113. if (clipboard_p >= clipboard_n) wimp_source = from_keyboard;
  1114. tty_ibuffer[tty_icount++] = c;
  1115. /*
  1116. * If the line ended at buffer full or with a newline I return
  1117. * the completed buffer. Otherwise I will drop through to wait for
  1118. * keyboard input to finish off the line.
  1119. */
  1120. if (c == '\n' || tty_icount == TTYBUF_SIZE)
  1121. { memcpy(tty_buffer, tty_ibuffer, TTYBUF_SIZE);
  1122. n = tty_icount;
  1123. tty_icount = 0;
  1124. tty_ready = NO;
  1125. return n;
  1126. }
  1127. }
  1128. break;
  1129. case from_file:
  1130. case from_keyboard:
  1131. break;
  1132. }
  1133. remove_ticker();
  1134. delink();
  1135. remove_hourglass();
  1136. win_claim_idle_events(txt_syshandle(session));
  1137. event_setmask((wimp_emask)0); /* permits null events to show up */
  1138. while (!tty_ready && wimp_source == from_keyboard) event_process();
  1139. memcpy(tty_buffer, tty_ibuffer, TTYBUF_SIZE);
  1140. relink();
  1141. add_ticker();
  1142. if (wimp_source != from_keyboard) goto mouse_directed_input;
  1143. n = tty_icount;
  1144. tty_icount = 0;
  1145. tty_ready = NO;
  1146. return n;
  1147. }
  1148. /*
  1149. * Start-up code for the window manager
  1150. */
  1151. static int CSL_initialise()
  1152. {
  1153. wimp_save_fp_state_on_poll();
  1154. wimpt_init("Codemist Lisp");
  1155. flex_init();
  1156. res_init(appname+1);
  1157. msgs_init();
  1158. resspr_init();
  1159. template_use_fancyfonts();
  1160. template_init();
  1161. dbox_init();
  1162. txt_init();
  1163. /*
  1164. * Create menu to associate with icon-bar object and attach it
  1165. */
  1166. if ((Iconbar_menu = menu_new(appname+1, ">Info,Quit")) == NULL) return NO;
  1167. baricon(appname, 1, CSL_clickproc);
  1168. if (!event_attachmenu(win_ICONBAR, Iconbar_menu, Iconbar_menuproc, 0))
  1169. return NO;
  1170. /*
  1171. * Register function to get "unknown" events
  1172. */
  1173. win_register_event_handler(win_ICONBARLOAD, CSL_load_events, 0);
  1174. win_claim_unknown_events(win_ICONBARLOAD);
  1175. tty_count = tty_icount = 0;
  1176. tty_ready = NO;
  1177. return YES;
  1178. }
  1179. void accept_tick()
  1180. /*
  1181. * My clock ticks ensure that this procedure is called fairly regularly...
  1182. */
  1183. {
  1184. if (under_wimp)
  1185. {
  1186. clock_t c0 = clock();
  1187. /*
  1188. * Here I ensure that the screen is brought up to date at least every 3
  1189. * seconds or so.
  1190. */
  1191. if (last_output_time == 0 || c0 > last_output_time + 3*CLOCKS_PER_SEC)
  1192. { int t, gct;
  1193. if (clock_stack == &consolidated_time[0])
  1194. { consolidated_time[0] += (double)(c0 - base_time)/(double)CLOCKS_PER_SEC;
  1195. base_time = c0;
  1196. }
  1197. t = (int)(100.0 * consolidated_time[0]);
  1198. gct = (int)(100.0 * gc_time);
  1199. report_time(t, gct);
  1200. push_clock();
  1201. ensure_screen();
  1202. }
  1203. else push_clock();
  1204. /*
  1205. * I also poll the window manager so that other tasks can get a look in
  1206. * and so that my window responds to drag events and is generally kept
  1207. * up to date on the screen.
  1208. */
  1209. remove_ticker();
  1210. delink();
  1211. win_claim_idle_events(txt_syshandle(session));
  1212. event_setmask((wimp_emask)0); /* permits null events to show up */
  1213. do
  1214. { done_something = 0;
  1215. event_process();
  1216. } while (done_something);
  1217. relink();
  1218. add_ticker();
  1219. /*
  1220. * Time spent doing all of this is counted as "overhead" or "system time"
  1221. * and not included in the times that I will report to my users...
  1222. */
  1223. pop_clock();
  1224. polltick_pending = NO;
  1225. }
  1226. }
  1227. void start_up_window_manager(int use_wimp)
  1228. {
  1229. int i, r0;
  1230. if (!use_wimp)
  1231. { under_wimp = NO;
  1232. last_output_time = clock();
  1233. return;
  1234. }
  1235. os_swi1r(Wimp_ReadSysInfo, 0, &r0);
  1236. if (r0 == 0) under_wimp = NO;
  1237. else
  1238. { under_wimp = YES;
  1239. if (!CSL_initialise())
  1240. { fprintf(stderr, "\nFailed to start the window manager - stopping\n");
  1241. exit(EXIT_FAILURE);
  1242. }
  1243. /*
  1244. * Now I hang, doing not a lot, until the main window gets opened...
  1245. */
  1246. while (!CSL_window_open) event_process();
  1247. os_swi0(Hourglass_On);
  1248. hourglass_showing = YES;
  1249. atexit(remove_hourglass);
  1250. win_claim_idle_events(txt_syshandle(session));
  1251. event_setmask((wimp_emask)0); /* permits null events to show up */
  1252. for (i=0; i<5; i++) event_process();
  1253. /* Maybe helps things become visible? */
  1254. last_output_time = clock();
  1255. }
  1256. }
  1257. #include "fileops.c"
  1258. /* end of sysarm.c */