1
/* OS/2 support fo ELinks. It has pretty different life than rest of ELinks. */
2
/* $Id: os2.c,v 1.16 2004/01/05 04:54:31 miciah Exp $ */
8
#include "osdep/system.h"
13
/* from xf86sup - XFree86 OS/2 support driver */
24
#include "osdep/os2/os2.h"
25
#include "osdep/osdep.h"
26
#include "terminal/terminal.h"
31
#define INCL_DOSPROCESS
32
#define INCL_DOSERRORS
33
#define INCL_WINCLIPBOARD
34
#define INCL_WINSWITCHLIST
38
#include <sys/video.h>
39
#ifdef HAVE_SYS_FMUTEX_H
40
#include <sys/builtin.h>
41
#include <sys/fmutex.h>
45
#define A_DECL(type, var) type var##1, var##2, *var = _THUNK_PTR_STRUCT_OK(&var##1) ? &var##1 : &var##2
52
if (xt == -1) xt = !!getenv("WINDOWID");
58
int winch_thread_running = 0;
60
#define WINCH_SLEEPTIME 500 /* time in ms for winch thread to sleep */
65
/* A thread which regularly checks whether the size of
66
window has changed. Then raise SIGWINCH or notifiy
67
the thread responsible to handle this. */
68
static int old_xsize, old_ysize;
69
static int cur_xsize, cur_ysize;
71
signal(SIGPIPE, SIG_IGN);
72
if (get_terminal_size(0, &old_xsize, &old_ysize)) return;
74
if (get_terminal_size(0, &cur_xsize, &cur_ysize)) return;
75
if ((old_xsize != cur_xsize) || (old_ysize != cur_ysize)) {
76
old_xsize = cur_xsize;
77
old_ysize = cur_ysize;
78
write(winch_pipe[1], "x", 1);
79
/* Resizing may take some time. So don't send a flood
81
_sleep2(2 * WINCH_SLEEPTIME);
83
_sleep2(WINCH_SLEEPTIME);
93
while (can_read(winch_pipe[0]) && safe_read(winch_pipe[0], &c, 1) == 1);
98
handle_terminal_resize(int fd, void (*fn)())
100
if (!is_xterm()) return;
101
if (!winch_thread_running) {
102
if (c_pipe(winch_pipe) < 0) return;
103
winch_thread_running = 1;
104
_beginthread((void (*)(void *))winch_thread, NULL, 0x32000, NULL);
106
set_handlers(winch_pipe[0], winch, NULL, NULL, fn);
110
unhandle_terminal_resize(int fd)
112
set_handlers(winch_pipe[0], NULL, NULL, NULL, NULL);
116
get_terminal_size(int fd, int *x, int *y)
118
if (!x || !y) return -1;
125
/* fd = STDIN_FILENO; */
126
arc = ptioctl(1, TIOCGWINSZ, &win);
138
DBG("%d %d", *x, *y);
154
*x = get_e("COLUMNS");
168
exe(unsigned char *path)
170
int flags = P_SESSION;
173
unsigned char *shell;
176
if (!shell) shell = DEFAULT_SHELL;
177
if (is_xterm()) flags |= P_BACKGROUND;
179
pid = spawnlp(flags, shell, shell, "/c", path, NULL);
181
waitpid(pid, &ret, 0);
187
get_clipboard_text(void)
194
unsigned char *ret = 0;
196
DosGetInfoBlocks(&tib, &pib);
198
oldType = pib->pib_ultype;
202
hab = WinInitialize(0);
203
if (hab != NULLHANDLE) {
204
hmq = WinCreateMsgQueue(hab, 0);
205
if (hmq != NULLHANDLE) {
206
if (WinOpenClipbrd(hab)) {
209
if (WinQueryClipbrdFmtInfo(hab, CF_TEXT, &fmtInfo) != FALSE) {
210
ULONG selClipText = WinQueryClipbrdData(hab, CF_TEXT);
213
PCHAR pchClipText = (PCHAR) selClipText;
215
ret = stracpy(pchClipText);
218
WinCloseClipbrd(hab);
220
WinDestroyMsgQueue(hmq);
225
pib->pib_ultype = oldType;
231
set_clipboard_text(unsigned char *data)
239
DosGetInfoBlocks(&tib, &pib);
241
oldType = pib->pib_ultype;
245
hab = WinInitialize(0);
246
if (hab != NULLHANDLE) {
247
hmq = WinCreateMsgQueue(hab, 0);
248
if (hmq != NULLHANDLE) {
249
if (WinOpenClipbrd(hab)) {
250
PVOID pvShrObject = NULL;
251
if (DosAllocSharedMem(&pvShrObject, NULL, strlen(data) + 1, PAG_COMMIT | PAG_WRITE | OBJ_GIVEABLE) == NO_ERROR) {
252
strcpy(pvShrObject, data);
253
WinSetClipbrdData(hab, (ULONG)pvShrObject, CF_TEXT, CFI_POINTER);
255
WinCloseClipbrd(hab);
257
WinDestroyMsgQueue(hmq);
262
pib->pib_ultype = oldType;
266
get_window_title(void)
269
unsigned char *org_switch_title;
270
unsigned char *org_win_title = NULL;
271
static PTIB tib = NULL;
272
static PPIB pib = NULL;
274
HSWITCH hSw = NULLHANDLE;
279
/* save current process title */
281
if (!pib) DosGetInfoBlocks(&tib, &pib);
282
oldType = pib->pib_ultype;
283
memset(&swData, 0, sizeof swData);
284
if (hSw == NULLHANDLE) hSw = WinQuerySwitchHandle(0, pib->pib_ulpid);
285
if (hSw != NULLHANDLE && !WinQuerySwitchEntry(hSw, &swData)) {
286
/*org_switch_title = mem_alloc(strlen(swData.szSwtitle)+1);
287
strcpy(org_switch_title, swData.szSwtitle);*/
290
hab = WinInitialize(0);
291
if (hab != NULLHANDLE) {
292
hmq = WinCreateMsgQueue(hab, 0);
293
if (hmq != NULLHANDLE) {
294
org_win_title = mem_alloc(MAXNAMEL + 1);
296
WinQueryWindowText(swData.hwnd,
299
org_win_title[MAXNAMEL] = 0;
301
WinDestroyMsgQueue(hmq);
305
pib->pib_ultype = oldType;
307
return org_win_title;
314
set_window_title(unsigned char *title)
324
unsigned char new_title[MAXNAMEL];
327
if (!pib) DosGetInfoBlocks(&tib, &pib);
328
oldType = pib->pib_ultype;
329
memset(&swData, 0, sizeof swData);
330
if (hSw == NULLHANDLE) hSw = WinQuerySwitchHandle(0, pib->pib_ulpid);
331
if (hSw != NULLHANDLE && !WinQuerySwitchEntry(hSw, &swData)) {
334
safe_strncpy(new_title, title, MAXNAMEL - 1);
335
while ((p = strchr(new_title, 1))) *p = ' ';
336
safe_strncpy(swData.szSwtitle, new_title, MAXNAMEL - 1);
337
WinChangeSwitchEntry(hSw, &swData);
340
hab = WinInitialize(0);
341
if (hab != NULLHANDLE) {
342
hmq = WinCreateMsgQueue(hab, 0);
343
if (hmq != NULLHANDLE) {
345
WinSetWindowText(swData.hwnd, new_title);
347
WinDestroyMsgQueue(hmq);
352
pib->pib_ultype = oldType;
358
set_window_title(int init, const char *url)
360
static char *org_switch_title;
361
static char *org_win_title;
364
static ULONG oldType;
366
static SWCNTRL swData;
369
char new_title[MAXNAMEL];
373
DosGetInfoBlocks(&tib, &pib);
374
oldType = pib->pib_ultype;
375
memset(&swData, 0, sizeof swData);
376
hSw = WinQuerySwitchHandle(0, pib->pib_ulpid);
377
if (hSw != NULLHANDLE && !WinQuerySwitchEntry(hSw, &swData)) {
378
org_switch_title = mem_alloc(strlen(swData.szSwtitle) + 1);
379
strcpy(org_switch_title, swData.szSwtitle);
381
hab = WinInitialize(0);
382
hmq = WinCreateMsgQueue(hab, 0);
383
if (hab != NULLHANDLE && hmq != NULLHANDLE) {
384
org_win_title = mem_alloc(MAXNAMEL + 1);
385
WinQueryWindowText(swData.hwnd, MAXNAMEL + 1, org_win_title);
386
WinDestroyMsgQueue(hmq);
389
pib->pib_ultype = oldType;
394
hab = WinInitialize(0);
395
hmq = WinCreateMsgQueue(hab, 0);
396
if (hSw != NULLHANDLE && hab != NULLHANDLE && hmq != NULLHANDLE) {
397
safe_strncpy(swData.szSwtitle, org_switch_title, MAXNAMEL);
398
WinChangeSwitchEntry(hSw, &swData);
401
WinSetWindowText(swData.hwnd, org_win_title);
402
WinDestroyMsgQueue(hmq);
405
pib->pib_ultype = oldType;
406
mem_free(org_switch_title);
407
mem_free(org_win_title);
411
safe_strncpy(new_title, url, MAXNAMEL - 10);
412
strcat(new_title, " - Links");
414
hab = WinInitialize(0);
415
hmq = WinCreateMsgQueue(hab, 0);
416
if (hSw != NULLHANDLE && hab != NULLHANDLE && hmq != NULLHANDLE) {
417
safe_strncpy(swData.szSwtitle, new_title, MAXNAMEL);
418
WinChangeSwitchEntry(hSw, &swData);
421
WinSetWindowText(swData.hwnd, new_title);
422
WinDestroyMsgQueue(hmq);
425
pib->pib_ultype = oldType;
433
resize_window(int x, int y)
435
A_DECL(VIOMODEINFO, vmi);
438
if (is_xterm()) return -1;
439
vmi->cb = sizeof(*vmi);
440
if (VioGetMode(vmi, 0)) return -1;
443
if (VioSetMode(vmi, 0)) return -1;
445
unsigned char cmdline[16];
446
sprintf(cmdline, "mode ");
447
snprint(cmdline + 5, 5, x);
448
strcat(cmdline, ",");
449
snprint(cmdline + strlen(cmdline), 5, y);
457
#ifdef HAVE_SYS_FMUTEX_H
459
int mouse_mutex_init = 0;
463
struct os2_mouse_spec {
465
void (*fn)(void *, unsigned char *, int);
467
unsigned char buffer[sizeof(struct term_event)];
473
mouse_thread(void *p)
476
struct os2_mouse_spec *oms = p;
478
A_DECL(MOUEVENTINFO, ms);
480
A_DECL(USHORT, mask);
481
struct term_event ev;
483
signal(SIGPIPE, SIG_IGN);
485
if (MouOpen(NULL, mh)) goto ret;
487
*mask = MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN1_DOWN |
488
MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_BN2_DOWN |
489
MOUSE_MOTION_WITH_BN3_DOWN | MOUSE_BN3_DOWN |
491
MouSetEventMask(mask, *mh);
498
if (MouReadEventQue(ms, rd, *mh)) break;
499
#ifdef HAVE_SYS_FMUTEX_H
500
_fmutex_request(&mouse_mutex, _FMR_IGNINT);
502
if (!oms->terminate) MouDrawPtr(*mh);
503
#ifdef HAVE_SYS_FMUTEX_H
504
_fmutex_release(&mouse_mutex);
508
/*DBG("status: %d %d %d", ms->col, ms->row, ms->fs);*/
509
if (ms->fs & (MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN))
510
ev.b = status = B_DOWN | (ms->fs & MOUSE_BN1_DOWN ? B_LEFT : ms->fs & MOUSE_BN2_DOWN ? B_MIDDLE : B_RIGHT);
511
else if (ms->fs & (MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_MOTION_WITH_BN3_DOWN)) {
512
int b = ms->fs & MOUSE_MOTION_WITH_BN1_DOWN ? B_LEFT : ms->fs & MOUSE_MOTION_WITH_BN2_DOWN ? B_MIDDLE : B_RIGHT;
520
if (status == -1) continue;
521
ev.b = (status & BM_BUTT) | B_UP;
524
if (hard_write(oms->p[1], (unsigned char *)&ev, sizeof(struct term_event)) != sizeof(struct term_event)) break;
526
#ifdef HAVE_SYS_FMUTEX_H
527
_fmutex_request(&mouse_mutex, _FMR_IGNINT);
531
#ifdef HAVE_SYS_FMUTEX_H
532
_fmutex_release(&mouse_mutex);
541
mouse_handle(struct os2_mouse_spec *oms)
543
int r = safe_read(oms->p[0], oms->buffer + oms->bufptr,
544
sizeof(struct term_event) - oms->bufptr);
552
if (oms->bufptr == sizeof(struct term_event)) {
554
oms->fn(oms->data, oms->buffer, sizeof(struct term_event));
559
handle_mouse(int cons, void (*fn)(void *, unsigned char *, int),
562
struct os2_mouse_spec *oms;
564
if (is_xterm()) return NULL;
565
#ifdef HAVE_SYS_FMUTEX_H
566
if (!mouse_mutex_init) {
567
if (_fmutex_create(&mouse_mutex, 0)) return NULL;
568
mouse_mutex_init = 1;
571
/* This is never freed but it's allocated only once */
572
oms = malloc(sizeof(struct os2_mouse_spec));
573
if (!oms) return NULL;
578
if (c_pipe(oms->p)) {
582
_beginthread(mouse_thread, NULL, 0x10000, (void *)oms);
583
set_handlers(oms->p[0], (void (*)(void *))mouse_handle, NULL, NULL, oms);
589
unhandle_mouse(void *om)
591
struct os2_mouse_spec *oms = om;
595
set_handlers(oms->p[0], NULL, NULL, NULL, NULL);
601
suspend_mouse(void *om)
606
resume_mouse(void *om)
613
A_DECL(NOPTRRECT, pa);
614
#ifdef HAVE_SYS_FMUTEX_H
615
if (mouse_mutex_init) _fmutex_request(&mouse_mutex, _FMR_IGNINT);
618
static int x = -1, y = -1;
621
if (x == -1 || y == -1 || (c != resize_count)) {
622
get_terminal_size(1, &x, &y);
630
MouRemovePtr(pa, mouse_h);
637
#ifdef HAVE_SYS_FMUTEX_H
638
if (mouse_mutex_init) _fmutex_release(&mouse_mutex);
642
#endif /* OS2_MOUSE */
648
return get_input_handle();
655
int env = get_common_env();
657
/* !!! FIXME: telnet */
658
if (!is_xterm()) env |= ENV_OS2VIO;
665
open_in_new_vio(struct terminal *term, unsigned char *exe_name,
666
unsigned char *param)
668
exec_new_elinks(term, DEFAULT_OS2_WINDOW_CMD, exe_name, param);
672
open_in_new_fullscreen(struct terminal *term, unsigned char *exe_name,
673
unsigned char *param)
675
exec_new_elinks(term, DEFAULT_OS2_FULLSCREEN_CMD, exe_name, param);
682
DosSetPriority(PRTYS_PROCESS, PRTYC_FOREGROUNDSERVER, 0, 0);
687
can_open_os_shell(int environment)
689
if (environment & ENV_XWIN) return 0;
694
#if defined(HAVE_BEGINTHREAD)
697
start_thread(void (*fn)(void *, int), void *ptr, int l)
702
if (c_pipe(p) < 0) return -1;
703
if (set_nonblocking_fd(p[0]) < 0) return -1;
704
if (set_nonblocking_fd(p[1]) < 0) return -1;
706
t = malloc(sizeof(struct tdata) + l);
710
memcpy(t->data, ptr, l);
711
if (_beginthread((void (*)(void *))bgt, NULL, 65536, t) == -1) {
721
#if defined(HAVE_READ_KBD)
727
input_thread(void *p)
732
signal(SIGPIPE, SIG_IGN);
735
c[0] = _read_kbd(0, 1, 1);
736
if (c[0]) if (safe_write(h, c, 1) <= 0) break;
739
printf("1");fflush(stdout);
740
c[1] = _read_kbd(0, 1, 1);
741
printf("2");fflush(stdout);
742
w = safe_write(h, c, 2);
743
printf("3");fflush(stdout);
745
if (w == 1) if (safe_write(h, c+1, 1) <= 0) break;
746
printf("4");fflush(stdout);
750
* _read_kbd(0, 1, 1) will
751
* read a char, don't echo it, wait for one available and
753
* Knowing that, I suggest we replace this call completly!
755
*c = _read_kbd(0, 1, 1);
762
get_input_handle(void)
766
if (ti != -1) return ti;
767
if (is_xterm()) return 0;
768
if (c_pipe(fd) < 0) return 0;
771
_beginthread(input_thread, NULL, 0x10000, (void *)tp);
780
#ifdef USE_OPEN_PREALLOC
782
open_prealloc(unsigned char *name, int flags, int mode, int siz)
784
/* This is good for OS/2, where this will prevent file fragmentation,
785
* preallocating the desired file size upon open(). */
786
return open(name, flags | O_SIZE, mode, (unsigned long) siz);
790
prealloc_truncate(int h, int siz)