1 /* -*- mode: hugs-c; -*- */
2 /* --------------------------------------------------------------------------
3 * Machine dependent code
4 * RISCOS specific code provided by Bryan Scatergood, JBS
5 * Macintosh specific code provided by Hans Aberg (haberg@matematik.su.se)
7 * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
8 * All rights reserved. See NOTICE for details and conditions of use etc...
9 * Hugs version 1.4, December 1997
11 * $RCSfile: machdep.c,v $
13 * $Date: 1998/12/02 13:22:20 $
14 * ------------------------------------------------------------------------*/
19 #include "hugs.h" /* for fromEnv */
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
37 # include <sys/param.h>
39 #ifdef HAVE_SYS_STAT_H
40 # include <sys/stat.h>
50 /* Windows/DOS include files */
54 #if defined HAVE_CONIO_H && ! HUGS_FOR_WINDOWS
71 extern HCURSOR HandCursor; /* Forward references to cursors */
72 extern HCURSOR GarbageCursor;
73 extern HCURSOR SaveCursor;
74 static void local DrawStatusLine Args((HWND));
79 extern unsigned _stklen = 8000; /* Allocate an 8k stack segment */
87 /* Macintosh include files */
110 /* --------------------------------------------------------------------------
111 * Find information about a file:
112 * ------------------------------------------------------------------------*/
114 static Bool local readable Args((String));
116 Void getFileInfo(f,tm,sz) /* find time stamp and size of file*/
120 #if defined HAVE_SYS_STAT_H || defined HAVE_STAT_H || defined HAVE_UNIX_H
122 if (!stat(f,&scbuf)) {
123 *tm = scbuf.st_mtime;
124 *sz = (Long)(scbuf.st_size);
129 #else /* normally just use stat() */
130 os_regset r; /* RISCOS PRM p.850 and p.837 */
131 r.r[0] = 17; /* Read catalogue, no path */
134 if(r.r[0] == 1 && (r.r[2] & 0xFFF00000) == 0xFFF00000) {
135 tm->hi = r.r[2] & 0xFF; /* Load address (high byte) */
136 tm->lo = r.r[3]; /* Execution address (low 4 bytes) */
137 } else { /* Not found, or not time-stamped */
140 *sz = (Long)(r.r[0] == 1 ? r.r[4] : 0);
144 #if defined HAVE_GETFINFO /* Mac971031 */
145 /* --------------------------------------------------------------------------
146 * Define a MacOS version of access():
147 * If the file is not accessible, -1 is returned and errno is set to
148 * the reason for the failure.
149 * If the file is accessible and the dummy is 0 (existence), 2 (write),
150 * or 4 (read), the return is 0.
151 * If the file is accessible, and the dummy is 1 (executable), then if
152 * the file is a program (of type 'APPL'), the return is 0, otherwise -1.
153 * Warnings: Use with caution. UNIX access do no translate to Macs.
154 * Check of write access is not implemented (same as read).
155 * ------------------------------------------------------------------------*/
157 int access(char *fileName, int dummy) {
161 errno = getfinfo(fileName, 0, &fi);
162 if (errno != 0) return -1; /* Check file accessible. */
164 /* Cases dummy = existence, read, write. */
165 if (dummy == 0 || dummy & 0x6) return 0;
167 /* Case dummy = executable. */
169 if (fi.fdType == 'APPL') return 0;
178 static Bool local readable(f) /* is f a regular, readable file */
180 #if DJGPP2 || defined HAVE_GETFINFO /* stat returns bogus mode bits on djgpp2 */
181 return (0 == access(f,4));
182 #elif defined HAVE_SYS_STAT_H || defined HAVE_STAT_H
184 return ( !stat(f,&scbuf)
185 && (scbuf.st_mode & S_IREAD) /* readable */
186 && (scbuf.st_mode & S_IFREG) /* regular file */
188 #elif defined HAVE_OS_SWI /* RISCOS specific */
189 os_regset r; /* RISCOS PRM p.850 -- JBS */
191 r.r[0] = 17; /* Read catalogue, no path */
194 return r.r[0] != 1; /* Does this check it's a regular file? ADR */
199 /* --------------------------------------------------------------------------
200 * Search for script files on the HUGS path:
201 * ------------------------------------------------------------------------*/
203 static String local hugsdir Args((Void));
204 static String local RealPath Args((String));
205 static String local normPath Args((String));
206 static Void local searchChr Args((Int));
207 static Void local searchStr Args((String));
208 static Bool local tryEndings Args((String));
212 # define isSLASH(c) ((c)=='\\' || (c)=='/')
214 # define DLL_ENDING ".dll"
217 # define isSLASH(c) ((c)==SLASH)
219 /* Mac PEF (Preferred Executable Format) file */
220 # define DLL_ENDING ".pef"
223 # define isSLASH(c) ((c)==SLASH)
225 # define DLL_ENDING ".so"
228 static String local hugsdir() { /* directory containing lib/Prelude.hs */
229 #if HAVE_GETMODULEFILENAME && !DOS
230 /* On Windows, we can find the binary we're running and it's
231 * conventional to put the libraries in the same place.
233 static char dir[FILENAME_MAX+1] = "";
234 if (dir[0] == '\0') { /* not initialised yet */
236 GetModuleFileName((HMODULE)0,dir,FILENAME_MAX+1);
237 if (dir[0] == '\0') { /* GetModuleFileName must have failed */
240 if (slash = strrchr(dir,SLASH)) { /* truncate after directory name */
246 /* On Unix systems, we can't find the binary we're running and
247 * the libraries may not be installed near the binary anyway.
248 * This forces us to use a hardwired path which is set at
249 * configuration time (--datadir=...).
255 static String local RealPath(s) /* Find absolute pathname of file */
257 #if HAVE__FULLPATH /* eg DOS */
258 static char path[FILENAME_MAX+1];
259 _fullpath(path,s,FILENAME_MAX+1);
260 #elif HAVE_REALPATH /* eg Unix */
261 static char path[MAXPATHLEN+1];
264 static char path[FILENAME_MAX+1];
270 int pathCmp(p1,p2) /* Compare paths after normalisation */
273 #if HAVE__FULLPATH /* eg DOS */
274 static char path1[FILENAME_MAX+1];
275 static char path2[FILENAME_MAX+1];
276 _fullpath(path1,p1,FILENAME_MAX+1);
277 _fullpath(path2,p2,FILENAME_MAX+1);
278 #elif HAVE_REALPATH /* eg Unix */
279 static char path1[MAXPATHLEN+1];
280 static char path2[MAXPATHLEN+1];
284 static char path1[FILENAME_MAX+1];
285 static char path2[FILENAME_MAX+1];
289 #if CASE_INSENSITIVE_FILENAMES
293 return filenamecmp(path1,path2);
296 static String local normPath(s) /* Try, as much as possible, to normalize */
297 String s; { /* a pathname in some appropriate manner. */
298 #if PATH_CANONICALIZATION
299 String path = RealPath(s);
300 #if CASE_INSENSITIVE_FILENAMES
301 strlwr(path); /* and convert to lowercase */
304 #else /* ! PATH_CANONICALIZATION */
306 #endif /* ! PATH_CANONICALIZATION */
309 static String endings[] = { "", ".myhi", ".hs", ".lhs", 0 };
310 static char searchBuf[FILENAME_MAX+1];
311 static Int searchPos;
313 #define searchReset(n) searchBuf[searchPos=(n)]='\0'
315 static Void local searchChr(c) /* Add single character to search buffer */
317 if (searchPos<FILENAME_MAX) {
318 searchBuf[searchPos++] = c;
319 searchBuf[searchPos] = '\0';
323 static Void local searchStr(s) /* Add string to search buffer */
325 while (*s && searchPos<FILENAME_MAX)
326 searchBuf[searchPos++] = *s++;
327 searchBuf[searchPos] = '\0';
330 static Bool local tryEndings(s) /* Try each of the listed endings */
334 for (; endings[i]; ++i) {
335 Int save = searchPos;
336 searchStr(endings[i]);
337 if (readable(searchBuf))
344 String findPathname(along,nm) /* Look for a file along specified path */
345 String along; /* Return NULL if file does not exist */
347 String s = findMPathname(along,nm);
348 return s ? s : normPath(searchBuf);
351 String findMPathname(along,nm) /* Look for a file along specified path */
352 String along; /* If nonzero, a path prefix from along is */
353 String nm; { /* used as the first prefix in the search. */
354 String pathpt = hugsPath;
357 if (along) { /* Was a path for an existing file given? */
360 for (; along[i]; i++) {
362 if (isSLASH(along[i]))
368 return normPath(searchBuf);
370 if (pathpt && *pathpt) { /* Otherwise, we look along the HUGSPATH */
375 if (*pathpt!=PATHSEP) {
376 /* Pre-define one MPW-style "shell-variable" */
377 if (strncmp(pathpt,"{Hugs}",6)==0) {
378 searchStr(hugsdir());
382 searchChr(*pathpt++);
383 while (*pathpt && *pathpt!=PATHSEP);
386 if (*pathpt==PATHSEP)
394 return normPath(searchBuf);
398 searchReset(0); /* As a last resort, look for file in the current dir */
399 return (tryEndings(nm) ? normPath(searchBuf) : 0);
402 /* --------------------------------------------------------------------------
403 * Substitute old value of path into empty entries in new path
404 * eg substPath("a:b:c::d:e","x:y:z") = "a:b:c:x:y:z:d:e"
405 * ------------------------------------------------------------------------*/
407 String substPath(new,sub) /* substitute sub path into new path*/
410 Bool substituted = FALSE; /* only allow one replacement */
411 Int maxlen = strlen(sub) + strlen(new); /* safe upper bound */
412 String r = (String) malloc(maxlen+1); /* result string */
413 String t = r; /* pointer into r */
414 String next = new; /* next uncopied char in new */
415 String start = next; /* start of last path component */
417 ERRMSG(0) "String storage space exhausted"
421 if (*next == PATHSEP || *next == '\0') {
422 if (!substituted && next == start) {
424 for(; *s != '\0'; ++s) {
431 } while ((*t++ = *next++) != '\0');
436 /* --------------------------------------------------------------------------
437 * Garbage collection notification:
438 * ------------------------------------------------------------------------*/
440 Bool gcMessages = FALSE; /* TRUE => print GC messages */
442 Void gcStarted() { /* notify garbage collector start */
444 SaveCursor = SetCursor(GarbageCursor);
452 Void gcScanning() { /* notify garbage collector scans */
459 Void gcRecovered(recovered) /* notify garbage collection done */
462 printf("%d}}",recovered);
466 SetCursor(SaveCursor);
470 Cell *CStackBase; /* Retain start of C control stack */
472 #if RISCOS /* Stack traversal for RISCOS */
474 /* Warning: The following code is specific to the Acorn ARM under RISCOS
475 (and C4). We must explicitly walk back through the stack frames, since
476 the stack is extended from the heap. (see PRM pp. 1757). gcCStack must
477 not be modified, since the offset '5' assumes that only v1 is used inside
478 this function. Hence we do all the real work in gcARM.
481 #define spreg 13 /* C3 has SP=R13 */
483 #define previousFrame(fp) ((int *)((fp)[-3]))
484 #define programCounter(fp) ((int *)((*(fp)-12) & ~0xFC000003))
485 #define isSubSPSP(w) (((w)&dontCare) == doCare)
486 #define doCare (0xE24DD000) /* SUB r13,r13,#0 */
487 #define dontCare (~0x00100FFF) /* S and # bits */
488 #define immediateArg(x) ( ((x)&0xFF) << (((x)&0xF00)>>7) )
490 static void gcARM(int *fp) {
491 int si = *programCounter(fp); /* Save instruction indicates how */
492 /* many registers in this frame */
494 if (si & (1<<0)) markWithoutMove(*regs--);
495 if (si & (1<<1)) markWithoutMove(*regs--);
496 if (si & (1<<2)) markWithoutMove(*regs--);
497 if (si & (1<<3)) markWithoutMove(*regs--);
498 if (si & (1<<4)) markWithoutMove(*regs--);
499 if (si & (1<<5)) markWithoutMove(*regs--);
500 if (si & (1<<6)) markWithoutMove(*regs--);
501 if (si & (1<<7)) markWithoutMove(*regs--);
502 if (si & (1<<8)) markWithoutMove(*regs--);
503 if (si & (1<<9)) markWithoutMove(*regs--);
504 if (previousFrame(fp)) {
505 /* The non-register stack space is for the previous frame is above
506 this fp, and not below the previous fp, because of the way stack
507 extension works. It seems the only way of discovering its size is
508 finding the SUB sp, sp, #? instruction by walking through the code
509 following the entry point.
511 int *oldpc = programCounter(previousFrame(fp));
513 for(i = 1; i < 6; ++i)
514 if(isSubSPSP(oldpc[i])) fsize += immediateArg(oldpc[i]) / 4;
515 for(i=1; i<=fsize; ++i)
516 markWithoutMove(fp[i]);
522 int *fp = 5 + &dummy;
525 fp = previousFrame(fp);
529 #else /* Garbage collection for standard stack machines */
531 Void gcCStack() { /* Garbage collect elements off */
532 Cell stackTop = NIL; /* C stack */
533 Cell *ptr = &stackTop;
535 if (((long)(ptr) - (long)(CStackBase))&1)
537 #elif STACK_ALIGNMENT == 2 /* eg Macintosh 68000 */
538 if (((long)(ptr) - (long)(CStackBase))&1)
541 if (((long)(ptr) - (long)(CStackBase))&3)
545 #define StackGrowsDown while (ptr<=CStackBase) markWithoutMove(*ptr++)
546 #define StackGrowsUp while (ptr>=CStackBase) markWithoutMove(*ptr--)
547 #define GuessDirection if (ptr>CStackBase) StackGrowsUp; else StackGrowsDown
549 #if STACK_DIRECTION > 0
551 #elif STACK_DIRECTION < 0
557 #if SIZEOF_INTP==4 && STACK_ALIGNMENT == 2 /* eg Macintosh 68000 */
558 ptr = (Cell *)((long)(&stackTop) + 2);
562 #undef StackGrowsDown
564 #undef GuessDirection
568 /* --------------------------------------------------------------------------
569 * Terminal dependent stuff:
570 * ------------------------------------------------------------------------*/
572 #if (HAVE_TERMIO_H | HAVE_SGTTY_H | HAVE_TERMIOS_H)
574 /* This is believed to be redundant! ADR */
576 # include <sys/ioctl.h>
579 /* The order of these three tests is very important because
580 * some systems have more than one of the requisite header file
581 * but only one of them seems to work.
582 * Anyone changing the order of the tests should try enabling each of the
583 * three branches in turn and write down which ones work as well as which
584 * OS/compiler they're using.
586 * OS Compiler sgtty termio termios notes
587 * Linux 2.0.18 gcc 2.7.2 absent works works 1
590 * 1) On Linux, termio.h just #includes termios.h and sgtty.h is
591 * implemented using termios.h.
592 * sgtty.h is in /usr/include/bsd which is not on my standard include
593 * path. Adding it does no harm but you might as well use termios.
595 * reid-alastair@cs.yale.edu
600 typedef struct termios TermParams;
601 #define getTerminal(tp) tcgetattr(fileno(stdin), &tp)
602 #define setTerminal(tp) tcsetattr(fileno(stdin), TCSAFLUSH, &tp)
603 #define noEcho(tp) tp.c_lflag &= ~(ICANON | ECHO); \
610 typedef struct sgttyb TermParams;
611 #define getTerminal(tp) ioctl(fileno(stdin),TIOCGETP,&tp)
612 #define setTerminal(tp) ioctl(fileno(stdin),TIOCSETP,&tp)
614 #define noEcho(tp) tp.sg_flags |= RAW; tp.sg_flags &= (~ECHO);
616 #define noEcho(tp) tp.sg_flags |= CBREAK; tp.sg_flags &= (~ECHO);
622 typedef struct termio TermParams;
623 #define getTerminal(tp) ioctl(fileno(stdin),TCGETA,&tp)
624 #define setTerminal(tp) ioctl(fileno(stdin),TCSETAF,&tp)
625 #define noEcho(tp) tp.c_lflag &= ~(ICANON | ECHO); \
631 static Bool messedWithTerminal = FALSE;
632 static TermParams originalSettings;
634 Void normalTerminal() { /* restore terminal initial state */
635 if (messedWithTerminal)
636 setTerminal(originalSettings);
639 Void noechoTerminal() { /* set terminal into noecho mode */
642 if (!messedWithTerminal) {
643 getTerminal(originalSettings);
644 messedWithTerminal = TRUE;
646 getTerminal(settings);
648 setTerminal(settings);
651 Int getTerminalWidth() { /* determine width of terminal */
653 #ifdef _M_UNIX /* SCO Unix 3.2.4 defines TIOCGWINSZ*/
654 #include <sys/stream.h> /* Required by sys/ptem.h */
655 #include <sys/ptem.h> /* Required to declare winsize */
657 static struct winsize terminalSize;
658 ioctl(fileno(stdout),TIOCGWINSZ,&terminalSize);
659 return (terminalSize.ws_col==0)? 80 : terminalSize.ws_col;
665 Int readTerminalChar() { /* read character from terminal */
666 return getchar(); /* without echo, assuming that */
667 } /* noechoTerminal() is active... */
671 Int readTerminalChar() { /* read character from terminal */
672 return getchar(); /* without echo, assuming that */
673 } /* noechoTerminal() is active... */
675 Int getTerminalWidth() {
676 return console_options.ncols;
679 Void normalTerminal() {
680 csetmode(C_ECHO, stdin);
683 Void noechoTerminal() {
684 csetmode(C_NOECHO, stdin);
687 #else /* no terminal driver - eg DOS, RISCOS */
689 static Bool terminalEchoReqd = TRUE;
691 Int getTerminalWidth() {
694 (void) os_swi3r(OS_ReadModeVariable, -1, 1, 0, &dummy, &dummy, &width);
701 Void normalTerminal() { /* restore terminal initial state */
702 terminalEchoReqd = TRUE;
705 Void noechoTerminal() { /* turn terminal echo on/off */
706 terminalEchoReqd = FALSE;
709 Int readTerminalChar() { /* read character from terminal */
710 if (terminalEchoReqd) {
714 return c=='\r' ? '\n' : c; /* slight paranoia about CR-LF */
718 #endif /* no terminal driver */
720 /* --------------------------------------------------------------------------
721 * Interrupt handling:
722 * ------------------------------------------------------------------------*/
725 static Bool breakReqd = FALSE;
726 static sigProto(ignoreBreak);
727 static Void local installHandlers Args((Void));
729 Bool breakOn(reqd) /* set break trapping on if reqd, */
730 Bool reqd; { /* or off otherwise, returning old */
731 Bool old = breakReqd;
735 if (broken) { /* repond to break signal received */
736 broken = FALSE; /* whilst break trap disabled */
737 sigRaise(breakHandler);
739 ctrlbrk(ignoreBreak);
741 ctrlbrk(ignoreBreak);
746 static sigHandler(ignoreBreak) { /* record but don't respond to break*/
747 ctrlbrk(ignoreBreak);
754 static sigProto(panic);
755 static sigHandler(panic) { /* exit in a panic, on receipt of */
756 everybody(EXIT); /* an unexpected signal */
757 fprintf(stderr,"\nUnexpected signal\n");
759 sigResume;/*NOTREACHED*/
761 #endif /* !DONT_PANIC */
763 static Void local installHandlers() { /* Install handlers for all fatal */
764 /* signals except SIGINT and SIGBREAK*/
765 #if !DONT_PANIC && !DOS
767 signal(SIGABRT,panic);
770 signal(SIGBUS,panic);
773 signal(SIGFPE,panic);
776 signal(SIGHUP,panic);
779 signal(SIGILL,panic);
782 signal(SIGQUIT,panic);
785 signal(SIGSEGV,panic);
788 signal(SIGTERM,panic);
790 #endif /* !DONT_PANIC && !DOS */
793 /* --------------------------------------------------------------------------
795 * ------------------------------------------------------------------------*/
797 Bool startEdit(line,nm) /* Start editor on file name at */
798 Int line; /* given line. Both name and line */
799 String nm; { /* or just line may be zero */
800 static char editorCmd[FILENAME_MAX+1];
803 if (hugsEdit && *hugsEdit) { /* Check that editor configured */
805 /* On a Mac, files have creator information, telling which program
806 to launch to, so an editor named to the empty string "" is often
808 if (hugsEdit) { /* Check that editor configured */
810 Int n = FILENAME_MAX;
811 String he = hugsEdit;
812 String ec = editorCmd;
813 String rd = NULL; /* Set to nonnull to redo ... */
815 for (; n>0 && *he && *he!=' '; n--)
816 *ec++ = *he++; /* Copy editor name to buffer */
817 /* assuming filename ends at space */
819 if (nm && line && n>1 && *he){ /* Name, line, and enough space */
820 rd = ec; /* save, in case we don't find name*/
823 if (*++he=='d' && n>10) {
824 sprintf(ec,"%d",line);
827 else if (*he=='s' && (size_t)n>strlen(nm)) {
832 else if (*he=='%' && n>1) {
836 else /* Ignore % char if not followed */
837 *ec = '\0'; /* by one of d, s, or %, */
838 for (; *ec && n>0; n--)
840 } /* ignore % followed by anything other than d, s, or % */
841 else { /* Copy other characters across */
850 if (rd) { /* If file name was not included */
855 if (nm && line==0 && n>1) { /* Name, but no line ... */
857 for (; n>0 && *nm; n--) /* ... just copy file name */
861 *ec = '\0'; /* Add terminating null byte */
864 ERRMSG(0) "Hugs is not configured to use an editor"
869 WinExec(editorCmd, SW_SHOW);
872 if (shellEsc(editorCmd))
873 Printf("Warning: Editor terminated abnormally\n");
878 Int shellEsc(s) /* run a shell command (or shell) */
885 s = fromEnv("SHELL","/bin/sh");
892 #if RISCOS /* RISCOS also needs a chdir() */
893 int chdir(char *s) { /* RISCOS PRM p. 885 -- JBS */
894 return os_swi2(OS_FSControl + XOS_Bit, 0, (int)s) != NULL;
896 #elif defined HAVE_PBHSETVOLSYNC /* Macintosh */
897 int chdir(const char *s) {
901 str = (char*)malloc(strlen(s) + 1);
902 if (str == 0) return -1;
904 wd.ioNamePtr = C2PStr(str);
907 errno = PBHSetVolSync(&wd);
918 /*---------------------------------------------------------------------------
919 * Printf-related operations:
920 *-------------------------------------------------------------------------*/
922 #if !defined(HAVE_VSNPRINTF)
923 int vsnprintf(buffer, count, fmt, ap)
928 #if defined(HAVE__VSNPRINTF)
929 return _vsnprintf(buffer, count, fmt, ap);
934 #endif /* HAVE_VSNPRINTF */
936 #if !defined(HAVE_SNPRINTF)
937 int snprintf(char* buffer, int count, const char* fmt, ...) {
938 #if defined(HAVE__VSNPRINTF)
940 va_list ap; /* pointer into argument list */
941 va_start(ap, fmt); /* make ap point to first arg after fmt */
942 r = vsnprintf(buffer, count, fmt, ap);
943 va_end(ap); /* clean up */
949 #endif /* HAVE_SNPRINTF */
951 /* --------------------------------------------------------------------------
952 * Read/write values from/to the registry
954 * All reads are from either HUGS_CURRENT_USER\\hugs_ROOT\\key or
955 * HUGS_LOCAL_MACHINE\\hugs_ROOT\\key. (Machine entry is only used if
956 * user entry doesn't exist).
958 * All writes are to HUGS_CURRENT_USER\\HugsRoot\\key
959 * ------------------------------------------------------------------------*/
963 #define HugsRoot ("SOFTWARE\\Haskell\\Hugs\\" HUGS_VERSION "\\")
965 static Bool local createKey Args((HKEY, PHKEY, REGSAM));
966 static Bool local queryValue Args((HKEY, String, LPDWORD, LPBYTE, DWORD));
967 static Bool local setValue Args((HKEY, String, DWORD, LPBYTE, DWORD));
969 static Bool local createKey(hKey, phRootKey, samDesired)
974 return RegCreateKeyEx(hKey, HugsRoot,
975 0, "", REG_OPTION_NON_VOLATILE,
976 samDesired, NULL, phRootKey, &dwDisp)
980 static Bool local queryValue(hKey, var, type, buf, bufSize)
988 if (!createKey(hKey, &hRootKey, KEY_READ)) {
991 LONG res = RegQueryValueEx(hRootKey, var, NULL, type, buf, &bufSize);
992 RegCloseKey(hRootKey);
993 return (res == ERROR_SUCCESS);
997 static Bool local setValue(hKey, var, type, buf, bufSize)
1005 if (!createKey(hKey, &hRootKey, KEY_WRITE)) {
1008 LONG res = RegSetValueEx(hRootKey, var, 0, type, buf, bufSize);
1009 RegCloseKey(hRootKey);
1010 return (res == ERROR_SUCCESS);
1014 String readRegString(var,def) /* read String from registry */
1017 static char buf[300];
1020 if (queryValue(HKEY_CURRENT_USER, var, &type, buf, sizeof(buf))
1021 && type == REG_SZ) {
1023 } else if (queryValue(HKEY_LOCAL_MACHINE, var, &type, buf, sizeof(buf))
1024 && type == REG_SZ) {
1031 Int readRegInt(var, def) /* read Int from registry */
1037 if (queryValue(HKEY_CURRENT_USER, var, &type,
1038 (LPBYTE)&buf, sizeof(buf))
1039 && type == REG_DWORD) {
1041 } else if (queryValue(HKEY_LOCAL_MACHINE, var, &type,
1042 (LPBYTE)&buf, sizeof(buf))
1043 && type == REG_DWORD) {
1050 Bool writeRegString(var,val) /* write String to registry */
1056 return setValue(HKEY_CURRENT_USER, var,
1057 REG_SZ, (LPBYTE)val, lstrlen(val)+1);
1060 Bool writeRegInt(var,val) /* write String to registry */
1063 return setValue(HKEY_CURRENT_USER, var,
1064 REG_DWORD, (LPBYTE)&val, sizeof(val));
1067 #endif /* USE_REGISTRY */
1069 /* --------------------------------------------------------------------------
1070 * Machine dependent control:
1071 * ------------------------------------------------------------------------*/
1073 Void machdep(what) /* Handle machine specific */
1074 Int what; { /* initialisation etc.. */
1077 case INSTALL : installHandlers();
1081 case EXIT : normalTerminal();
1082 #if HUGS_FOR_WINDOWS
1084 DestroyWindow(hWndMain);
1086 SetCursor(LoadCursor(NULL,IDC_ARROW));
1092 /*-------------------------------------------------------------------------*/