1 /* OS/2 support fo ELinks. It has pretty different life than rest of ELinks. */
7 #include "osdep/system.h"
10 /* from xf86sup - XFree86 OS/2 support driver */
21 #include "osdep/os2/os2.h"
22 #include "osdep/osdep.h"
23 #include "terminal/mouse.h"
24 #include "terminal/terminal.h"
25 #include "util/conv.h"
30 #define INCL_DOSPROCESS
31 #define INCL_DOSERRORS
32 #define INCL_WINCLIPBOARD
33 #define INCL_WINSWITCHLIST
37 #include <sys/video.h>
38 #ifdef HAVE_SYS_FMUTEX_H
39 #include <sys/builtin.h>
40 #include <sys/fmutex.h>
44 #define A_DECL(type, var) type var##1, var##2, *var = _THUNK_PTR_STRUCT_OK(&var##1) ? &var##1 : &var##2
51 if (xt
== -1) xt
= !!getenv("WINDOWID");
57 int winch_thread_running
= 0;
59 #define WINCH_SLEEPTIME 500 /* time in ms for winch thread to sleep */
64 /* A thread which regularly checks whether the size of
65 window has changed. Then raise SIGWINCH or notifiy
66 the thread responsible to handle this. */
67 static int old_xsize
, old_ysize
;
68 static int cur_xsize
, cur_ysize
;
70 signal(SIGPIPE
, SIG_IGN
);
71 if (get_terminal_size(0, &old_xsize
, &old_ysize
)) return;
73 if (get_terminal_size(0, &cur_xsize
, &cur_ysize
)) return;
74 if ((old_xsize
!= cur_xsize
) || (old_ysize
!= cur_ysize
)) {
75 old_xsize
= cur_xsize
;
76 old_ysize
= cur_ysize
;
77 write(winch_pipe
[1], "x", 1);
78 /* Resizing may take some time. So don't send a flood
80 _sleep2(2 * WINCH_SLEEPTIME
);
82 _sleep2(WINCH_SLEEPTIME
);
92 while (can_read(winch_pipe
[0]) && safe_read(winch_pipe
[0], &c
, 1) == 1);
97 handle_terminal_resize(int fd
, void (*fn
)())
99 if (!is_xterm()) return;
100 if (!winch_thread_running
) {
101 if (c_pipe(winch_pipe
) < 0) return;
102 winch_thread_running
= 1;
103 _beginthread((void (*)(void *)) winch_thread
, NULL
, 0x32000, NULL
);
105 set_handlers(winch_pipe
[0], winch
, NULL
, NULL
, fn
);
109 unhandle_terminal_resize(int fd
)
111 clear_handlers(winch_pipe
[0]);
115 get_terminal_size(int fd
, int *x
, int *y
)
123 /* fd = STDIN_FILENO; */
124 arc
= ptioctl(1, TIOCGWINSZ
, &win
);
129 *x
= DEFAULT_TERMINAL_WIDTH
;
130 *y
= DEFAULT_TERMINAL_HEIGHT
;
136 DBG("%d %d", *x, *y);
140 *x
= DEFAULT_TERMINAL_WIDTH
;
141 *y
= DEFAULT_TERMINAL_HEIGHT
;
150 *x
= get_e("COLUMNS");
151 if (!*x
) *x
= DEFAULT_TERMINAL_WIDTH
;
155 if (!*y
) *y
= DEFAULT_TERMINAL_HEIGHT
;
162 exe(unsigned char *path
)
164 int flags
= P_SESSION
;
167 unsigned char *shell
= get_shell();
169 if (is_xterm()) flags
|= P_BACKGROUND
;
171 pid
= spawnlp(flags
, shell
, shell
, "/c", path
, (char *) NULL
);
173 waitpid(pid
, &ret
, 0);
179 get_clipboard_text(void)
186 unsigned char *ret
= 0;
188 DosGetInfoBlocks(&tib
, &pib
);
190 oldType
= pib
->pib_ultype
;
194 hab
= WinInitialize(0);
195 if (hab
!= NULLHANDLE
) {
196 hmq
= WinCreateMsgQueue(hab
, 0);
197 if (hmq
!= NULLHANDLE
) {
198 if (WinOpenClipbrd(hab
)) {
201 if (WinQueryClipbrdFmtInfo(hab
, CF_TEXT
, &fmtInfo
) != FALSE
) {
202 ULONG selClipText
= WinQueryClipbrdData(hab
, CF_TEXT
);
205 PCHAR pchClipText
= (PCHAR
) selClipText
;
207 ret
= stracpy(pchClipText
);
210 WinCloseClipbrd(hab
);
212 WinDestroyMsgQueue(hmq
);
217 pib
->pib_ultype
= oldType
;
223 set_clipboard_text(unsigned char *data
)
231 DosGetInfoBlocks(&tib
, &pib
);
233 oldType
= pib
->pib_ultype
;
237 hab
= WinInitialize(0);
238 if (hab
!= NULLHANDLE
) {
239 hmq
= WinCreateMsgQueue(hab
, 0);
240 if (hmq
!= NULLHANDLE
) {
241 if (WinOpenClipbrd(hab
)) {
242 PVOID pvShrObject
= NULL
;
243 if (DosAllocSharedMem(&pvShrObject
, NULL
, strlen(data
) + 1, PAG_COMMIT
| PAG_WRITE
| OBJ_GIVEABLE
) == NO_ERROR
) {
244 strcpy(pvShrObject
, data
);
245 WinSetClipbrdData(hab
, (ULONG
) pvShrObject
, CF_TEXT
, CFI_POINTER
);
247 WinCloseClipbrd(hab
);
249 WinDestroyMsgQueue(hmq
);
254 pib
->pib_ultype
= oldType
;
258 get_window_title(void)
261 unsigned char *org_switch_title
;
262 unsigned char *org_win_title
= NULL
;
263 static PTIB tib
= NULL
;
264 static PPIB pib
= NULL
;
266 HSWITCH hSw
= NULLHANDLE
;
271 /* save current process title */
273 if (!pib
) DosGetInfoBlocks(&tib
, &pib
);
274 oldType
= pib
->pib_ultype
;
275 memset(&swData
, 0, sizeof(swData
));
276 if (hSw
== NULLHANDLE
) hSw
= WinQuerySwitchHandle(0, pib
->pib_ulpid
);
277 if (hSw
!= NULLHANDLE
&& !WinQuerySwitchEntry(hSw
, &swData
)) {
278 /*org_switch_title = mem_alloc(strlen(swData.szSwtitle)+1);
279 strcpy(org_switch_title, swData.szSwtitle);*/
282 hab
= WinInitialize(0);
283 if (hab
!= NULLHANDLE
) {
284 hmq
= WinCreateMsgQueue(hab
, 0);
285 if (hmq
!= NULLHANDLE
) {
286 org_win_title
= mem_alloc(MAXNAMEL
+ 1);
288 WinQueryWindowText(swData
.hwnd
,
291 org_win_title
[MAXNAMEL
] = 0;
293 WinDestroyMsgQueue(hmq
);
297 pib
->pib_ultype
= oldType
;
299 return org_win_title
;
306 set_window_title(unsigned char *title
, int codepage
)
316 unsigned char new_title
[MAXNAMEL
];
319 if (!pib
) DosGetInfoBlocks(&tib
, &pib
);
320 oldType
= pib
->pib_ultype
;
321 memset(&swData
, 0, sizeof(swData
));
322 if (hSw
== NULLHANDLE
) hSw
= WinQuerySwitchHandle(0, pib
->pib_ulpid
);
323 if (hSw
!= NULLHANDLE
&& !WinQuerySwitchEntry(hSw
, &swData
)) {
326 safe_strncpy(new_title
, title
, MAXNAMEL
- 1);
327 sanitize_title(new_title
);
328 safe_strncpy(swData
.szSwtitle
, new_title
, MAXNAMEL
- 1);
329 WinChangeSwitchEntry(hSw
, &swData
);
332 hab
= WinInitialize(0);
333 if (hab
!= NULLHANDLE
) {
334 hmq
= WinCreateMsgQueue(hab
, 0);
335 if (hmq
!= NULLHANDLE
) {
337 WinSetWindowText(swData
.hwnd
, new_title
);
339 WinDestroyMsgQueue(hmq
);
344 pib
->pib_ultype
= oldType
;
350 set_window_title(int init
, const char *url
)
352 static char *org_switch_title
;
353 static char *org_win_title
;
356 static ULONG oldType
;
358 static SWCNTRL swData
;
361 char new_title
[MAXNAMEL
];
365 DosGetInfoBlocks(&tib
, &pib
);
366 oldType
= pib
->pib_ultype
;
367 memset(&swData
, 0, sizeof(swData
));
368 hSw
= WinQuerySwitchHandle(0, pib
->pib_ulpid
);
369 if (hSw
!= NULLHANDLE
&& !WinQuerySwitchEntry(hSw
, &swData
)) {
370 org_switch_title
= mem_alloc(strlen(swData
.szSwtitle
) + 1);
371 strcpy(org_switch_title
, swData
.szSwtitle
);
373 hab
= WinInitialize(0);
374 hmq
= WinCreateMsgQueue(hab
, 0);
375 if (hab
!= NULLHANDLE
&& hmq
!= NULLHANDLE
) {
376 org_win_title
= mem_alloc(MAXNAMEL
+ 1);
377 WinQueryWindowText(swData
.hwnd
, MAXNAMEL
+ 1, org_win_title
);
378 WinDestroyMsgQueue(hmq
);
381 pib
->pib_ultype
= oldType
;
386 hab
= WinInitialize(0);
387 hmq
= WinCreateMsgQueue(hab
, 0);
388 if (hSw
!= NULLHANDLE
&& hab
!= NULLHANDLE
&& hmq
!= NULLHANDLE
) {
389 safe_strncpy(swData
.szSwtitle
, org_switch_title
, MAXNAMEL
);
390 WinChangeSwitchEntry(hSw
, &swData
);
393 WinSetWindowText(swData
.hwnd
, org_win_title
);
394 WinDestroyMsgQueue(hmq
);
397 pib
->pib_ultype
= oldType
;
398 mem_free(org_switch_title
);
399 mem_free(org_win_title
);
403 safe_strncpy(new_title
, url
, MAXNAMEL
- 10);
404 strcat(new_title
, " - Links");
406 hab
= WinInitialize(0);
407 hmq
= WinCreateMsgQueue(hab
, 0);
408 if (hSw
!= NULLHANDLE
&& hab
!= NULLHANDLE
&& hmq
!= NULLHANDLE
) {
409 safe_strncpy(swData
.szSwtitle
, new_title
, MAXNAMEL
);
410 WinChangeSwitchEntry(hSw
, &swData
);
413 WinSetWindowText(swData
.hwnd
, new_title
);
414 WinDestroyMsgQueue(hmq
);
417 pib
->pib_ultype
= oldType
;
425 resize_window(int x
, int y
, int old_width
, int old_height
)
427 A_DECL(VIOMODEINFO
, vmi
);
430 if (is_xterm()) return -1;
431 vmi
->cb
= sizeof(*vmi
);
432 if (VioGetMode(vmi
, 0)) return -1;
435 if (VioSetMode(vmi
, 0)) return -1;
437 unsigned char cmdline
[16];
438 sprintf(cmdline
, "mode ");
439 ulongcat(cmdline
+ 5, NULL
, x
, 5, 0);
440 strcat(cmdline
, ",");
441 ulongcat(cmdline
+ strlen(cmdline
), NULL
, y
, 5, 0);
449 #ifdef HAVE_SYS_FMUTEX_H
451 int mouse_mutex_init
= 0;
455 struct os2_mouse_spec
{
457 void (*fn
)(void *, unsigned char *, int);
459 unsigned char buffer
[sizeof(struct interlink_event
)];
465 mouse_thread(void *p
)
468 struct os2_mouse_spec
*oms
= p
;
470 A_DECL(MOUEVENTINFO
, ms
);
472 A_DECL(USHORT
, mask
);
474 signal(SIGPIPE
, SIG_IGN
);
475 if (MouOpen(NULL
, mh
)) goto ret
;
477 *mask
= MOUSE_MOTION_WITH_BN1_DOWN
| MOUSE_BN1_DOWN
|
478 MOUSE_MOTION_WITH_BN2_DOWN
| MOUSE_BN2_DOWN
|
479 MOUSE_MOTION_WITH_BN3_DOWN
| MOUSE_BN3_DOWN
|
481 MouSetEventMask(mask
, *mh
);
486 struct interlink_event ev
;
487 struct interlink_event_mouse mouse
;
490 if (MouReadEventQue(ms
, rd
, *mh
)) break;
491 #ifdef HAVE_SYS_FMUTEX_H
492 _fmutex_request(&mouse_mutex
, _FMR_IGNINT
);
494 if (!oms
->terminate
) MouDrawPtr(*mh
);
495 #ifdef HAVE_SYS_FMUTEX_H
496 _fmutex_release(&mouse_mutex
);
500 /*DBG("status: %d %d %d", ms->col, ms->row, ms->fs);*/
501 if (ms
->fs
& (MOUSE_BN1_DOWN
| MOUSE_BN2_DOWN
| MOUSE_BN3_DOWN
))
502 mouse
.button
= status
= B_DOWN
| (ms
->fs
& MOUSE_BN1_DOWN
? B_LEFT
: ms
->fs
& MOUSE_BN2_DOWN
? B_MIDDLE
: B_RIGHT
);
503 else if (ms
->fs
& (MOUSE_MOTION_WITH_BN1_DOWN
| MOUSE_MOTION_WITH_BN2_DOWN
| MOUSE_MOTION_WITH_BN3_DOWN
)) {
504 int b
= ms
->fs
& MOUSE_MOTION_WITH_BN1_DOWN
? B_LEFT
: ms
->fs
& MOUSE_MOTION_WITH_BN2_DOWN
? B_MIDDLE
: B_RIGHT
;
510 mouse
.button
= status
= b
;
512 if (status
== -1) continue;
513 mouse
.button
= (status
& BM_BUTT
) | B_UP
;
517 set_mouse_interlink_event(&ev
, mouse
.x
, mouse
.y
, mouse
.button
);
518 if (hard_write(oms
->p
[1], (unsigned char *) &ev
, sizeof(ev
)) != sizeof(ev
)) break;
520 #ifdef HAVE_SYS_FMUTEX_H
521 _fmutex_request(&mouse_mutex
, _FMR_IGNINT
);
525 #ifdef HAVE_SYS_FMUTEX_H
526 _fmutex_release(&mouse_mutex
);
535 mouse_handle(struct os2_mouse_spec
*oms
)
537 ssize_t r
= safe_read(oms
->p
[0], oms
->buffer
+ oms
->bufptr
,
538 sizeof(struct interlink_event
) - oms
->bufptr
);
546 if (oms
->bufptr
== sizeof(struct interlink_event
)) {
548 oms
->fn(oms
->data
, oms
->buffer
, sizeof(struct interlink_event
));
553 handle_mouse(int cons
, void (*fn
)(void *, unsigned char *, int),
556 struct os2_mouse_spec
*oms
;
558 if (is_xterm()) return NULL
;
559 #ifdef HAVE_SYS_FMUTEX_H
560 if (!mouse_mutex_init
) {
561 if (_fmutex_create(&mouse_mutex
, 0)) return NULL
;
562 mouse_mutex_init
= 1;
565 /* This is never freed but it's allocated only once */
566 oms
= malloc(sizeof(*oms
));
567 if (!oms
) return NULL
;
572 if (c_pipe(oms
->p
)) {
576 _beginthread(mouse_thread
, NULL
, 0x10000, (void *) oms
);
577 set_handlers(oms
->p
[0], (select_handler_T
) mouse_handle
, NULL
, NULL
, oms
);
583 unhandle_mouse(void *om
)
585 struct os2_mouse_spec
*oms
= om
;
589 clear_handlers(oms
->p
[0]);
595 suspend_mouse(void *om
)
600 resume_mouse(void *om
)
607 A_DECL(NOPTRRECT
, pa
);
608 #ifdef HAVE_SYS_FMUTEX_H
609 if (mouse_mutex_init
) _fmutex_request(&mouse_mutex
, _FMR_IGNINT
);
612 static int x
= -1, y
= -1;
615 if (x
== -1 || y
== -1 || (c
!= resize_count
)) {
616 get_terminal_size(1, &x
, &y
);
624 MouRemovePtr(pa
, mouse_h
);
631 #ifdef HAVE_SYS_FMUTEX_H
632 if (mouse_mutex_init
) _fmutex_release(&mouse_mutex
);
636 #endif /* OS2_MOUSE */
642 return get_input_handle();
649 int env
= get_common_env();
651 /* !!! FIXME: telnet */
652 if (!is_xterm()) env
|= ENV_OS2VIO
;
661 DosSetPriority(PRTYS_PROCESS
, PRTYC_FOREGROUNDSERVER
, 0, 0);
666 can_open_os_shell(int environment
)
668 if (environment
& ENV_XWIN
) return 0;
673 #if defined(HAVE_BEGINTHREAD)
676 start_thread(void (*fn
)(void *, int), void *ptr
, int l
)
681 if (c_pipe(p
) < 0) return -1;
682 if (set_nonblocking_fd(p
[0]) < 0) return -1;
683 if (set_nonblocking_fd(p
[1]) < 0) return -1;
685 t
= malloc(sizeof(*t
) + l
);
689 memcpy(t
->data
, ptr
, l
);
690 if (_beginthread((void (*)(void *)) bgt
, NULL
, 65536, t
) == -1) {
700 #if defined(HAVE_READ_KBD)
706 input_thread(void *p
)
711 signal(SIGPIPE
, SIG_IGN
);
714 c
[0] = _read_kbd(0, 1, 1);
715 if (c
[0]) if (safe_write(h
, c
, 1) <= 0) break;
718 printf("1");fflush(stdout
);
719 c
[1] = _read_kbd(0, 1, 1);
720 printf("2");fflush(stdout
);
721 w
= safe_write(h
, c
, 2);
722 printf("3");fflush(stdout
);
724 if (w
== 1) if (safe_write(h
, c
+1, 1) <= 0) break;
725 printf("4");fflush(stdout
);
729 * _read_kbd(0, 1, 1) will
730 * read a char, don't echo it, wait for one available and
732 * Knowing that, I suggest we replace this call completly!
734 *c
= _read_kbd(0, 1, 1);
741 get_input_handle(void)
745 if (ti
!= -1) return ti
;
746 if (is_xterm()) return 0;
747 if (c_pipe(fd
) < 0) return 0;
750 _beginthread(input_thread
, NULL
, 0x10000, (void *) tp
);
759 #ifdef USE_OPEN_PREALLOC
761 open_prealloc(unsigned char *name
, int flags
, int mode
, off_t siz
)
763 /* This is good for OS/2, where this will prevent file fragmentation,
764 * preallocating the desired file size upon open(). */
765 return open(name
, flags
| O_SIZE
, mode
, (unsigned long) siz
);
769 prealloc_truncate(int h
, off_t siz
)