📄 os_dep.c
字号:
char buffer[1024]; unsigned char *x1; if (is_xterm()) return -1; if (get_terminal_size(1, &old_x, &old_y)) return -1; x1 = GETSHELL; if (!x1) x1 = DEFAULT_SHELL; if (!is_winnt()) { ct = GetConsoleTitle(buffer, sizeof buffer); } call_resize(x1, x, y); if (!is_winnt()) { int new_x, new_y; /* If we resize console on Win98 in fullscreen mode, it won't be notified by Cygwin (it is valid for all Cygwin apps). So we must switch to windowed mode, resize it again (twice, because resizing to the same size won't have an effect) and switch back to full-screen mode. */ /* I'm not sure what's the behavior on WinNT 4. Anybody wants to test? */ if (!fullscreen && !get_terminal_size(1, &new_x, &new_y) && (new_x != x || new_y != y)) { fullscreen = 1; keybd_event(VK_MENU, 0x38, 0, 0); keybd_event(VK_RETURN, 0x1c, 0, 0); keybd_event(VK_RETURN, 0x1c, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0x38, KEYEVENTF_KEYUP, 0); if (y != 25) call_resize(x1, 80, 25); else call_resize(x1, 80, 50); call_resize(x1, x, y); if (get_terminal_size(1, &new_x, &new_y) || new_x != x || new_y != y) call_resize(x1, old_x, old_y); keybd_event(VK_MENU, 0x38, 0, 0); keybd_event(VK_RETURN, 0x1c, 0, 0); keybd_event(VK_RETURN, 0x1c, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0x38, KEYEVENTF_KEYUP, 0); } if (ct) SetConsoleTitle(buffer); } return 0;}#elif defined(OS2)#ifdef G_fmutex fd_mutex;int fd_mutex_init = 0;#endifint exe(char *path, int fg){ int flags = P_SESSION; pid_t pid; int ret;#ifdef G int old0 = 0, old1 = 1, old2 = 2;#endif char *shell; fg=fg; /* ignore flag */ if (!(shell = GETSHELL)) shell = DEFAULT_SHELL; if (is_xterm()) flags |= P_BACKGROUND;#ifdef G if (F) { if (!fd_mutex_init) { if (_fmutex_create(&fd_mutex, 0)) return -1; fd_mutex_init = 1; } _fmutex_request(&fd_mutex, _FMR_IGNINT); old0 = dup(0); old1 = dup(1); old2 = dup(2); close(0); close(1); close(2); open("con", O_RDONLY); open("con", O_WRONLY); open("con", O_WRONLY); }#endif pid = spawnlp(flags, shell, shell, "/c", path, NULL);#ifdef G if (F) { dup2(old0, 0); dup2(old1, 1); dup2(old2, 2); close(old0); close(old1); close(old2); _fmutex_release(&fd_mutex); }#endif if (pid != -1) waitpid(pid, &ret, 0); else ret = -1; return ret;}unsigned char *get_clipboard_text(struct terminal *term){ PTIB tib; PPIB pib; HAB hab; HMQ hmq; ULONG oldType; char *ret = NULL; DosGetInfoBlocks(&tib, &pib); oldType = pib->pib_ultype; pib->pib_ultype = 3; if ((hab = WinInitialize(0)) != NULLHANDLE) { if ((hmq = WinCreateMsgQueue(hab, 0)) != NULLHANDLE) { if (WinOpenClipbrd(hab)) { ULONG fmtInfo = 0; if (WinQueryClipbrdFmtInfo(hab, CF_TEXT, &fmtInfo)!=FALSE) { ULONG selClipText = WinQueryClipbrdData(hab, CF_TEXT); if (selClipText) { char *u; PCHAR pchClipText = (PCHAR)selClipText; ret = mem_alloc(strlen(pchClipText)+1); strcpy(ret, pchClipText); while ((u = strchr(ret, 13))) memmove(u, u + 1, strlen(u + 1) + 1); } } WinCloseClipbrd(hab); }#ifdef G if (F && ret) { static int cp = -1; struct conv_table *ct; unsigned char *d; if (cp == -1) { int c = WinQueryCp(hmq); unsigned char a[64]; snprintf(a, 64, "%d", c); if ((cp = get_cp_index(a)) < 0 || is_cp_special(cp)) cp = 0; } ct = get_translation_table(cp, get_cp_index("utf-8")); d = convert_string(ct, ret, strlen(ret), NULL); mem_free(ret); ret = d; }#endif WinDestroyMsgQueue(hmq); } WinTerminate(hab); } pib->pib_ultype = oldType; return ret;}void set_clipboard_text(struct terminal * term, unsigned char *data){ PTIB tib; PPIB pib; HAB hab; HMQ hmq; ULONG oldType; unsigned char *d = NULL; DosGetInfoBlocks(&tib, &pib); oldType = pib->pib_ultype; pib->pib_ultype = 3; if ((hab = WinInitialize(0)) != NULLHANDLE) { if ((hmq = WinCreateMsgQueue(hab, 0)) != NULLHANDLE) {#ifdef G if (F) { static int cp = -1; struct conv_table *ct; if (cp == -1) { int c = WinQueryCp(hmq); unsigned char a[64]; snprintf(a, 64, "%d", c); if ((cp = get_cp_index(a)) < 0 || is_cp_special(cp)) cp = 0; } ct = get_translation_table(get_cp_index("utf-8"), cp); d = convert_string(ct, data, strlen(data), NULL); data = d; }#endif if(WinOpenClipbrd(hab)) { PVOID pvShrObject = NULL; if (DosAllocSharedMem(&pvShrObject, NULL, strlen(data)+1, PAG_COMMIT | PAG_WRITE | OBJ_GIVEABLE) == NO_ERROR) { strcpy(pvShrObject, data); WinEmptyClipbrd(hab); WinSetClipbrdData(hab, (ULONG)pvShrObject, CF_TEXT, CFI_POINTER); } WinCloseClipbrd(hab); } WinDestroyMsgQueue(hmq); } WinTerminate(hab); } pib->pib_ultype = oldType; if (d) mem_free(d);}int clipboard_support(struct terminal *term){ return 1;}unsigned char *get_window_title(void){#ifndef OS2_DEBUG /*char *org_switch_title;*/ char *org_win_title = NULL; static PTIB tib = NULL; static PPIB pib = NULL; ULONG oldType; HSWITCH hSw = NULLHANDLE; SWCNTRL swData; HAB hab; HMQ hmq; /* save current process title */ if (!pib) DosGetInfoBlocks(&tib, &pib); oldType = pib->pib_ultype; memset(&swData, 0, sizeof swData); if (hSw == NULLHANDLE) hSw = WinQuerySwitchHandle(0, pib->pib_ulpid); if (hSw!=NULLHANDLE && !WinQuerySwitchEntry(hSw, &swData)) { /*org_switch_title = mem_alloc(strlen(swData.szSwtitle)+1); strcpy(org_switch_title, swData.szSwtitle);*/ /* Go to PM */ pib->pib_ultype = 3; if ((hab = WinInitialize(0)) != NULLHANDLE) { if ((hmq = WinCreateMsgQueue(hab, 0)) != NULLHANDLE) { org_win_title = mem_alloc(MAXNAMEL+1); WinQueryWindowText(swData.hwnd, MAXNAMEL+1, org_win_title); org_win_title[MAXNAMEL] = 0; /* back From PM */ WinDestroyMsgQueue(hmq); } WinTerminate(hab); } pib->pib_ultype = oldType; } return org_win_title;#else return NULL;#endif}void set_window_title(unsigned char *title){#ifndef OS2_DEBUG static PTIB tib; static PPIB pib; ULONG oldType; static HSWITCH hSw; SWCNTRL swData; HAB hab; HMQ hmq; if (!title) return; if (!pib) DosGetInfoBlocks(&tib, &pib); oldType = pib->pib_ultype; memset(&swData, 0, sizeof swData); if (hSw == NULLHANDLE) hSw = WinQuerySwitchHandle(0, pib->pib_ulpid); if (hSw!=NULLHANDLE && !WinQuerySwitchEntry(hSw, &swData)) { strncpy(swData.szSwtitle, title, MAXNAMEL-1); swData.szSwtitle[MAXNAMEL-1] = 0; WinChangeSwitchEntry(hSw, &swData); /* Go to PM */ pib->pib_ultype = 3; if ((hab = WinInitialize(0)) != NULLHANDLE) { if ((hmq = WinCreateMsgQueue(hab, 0)) != NULLHANDLE) { if(swData.hwnd) WinSetWindowText(swData.hwnd, title); /* back From PM */ WinDestroyMsgQueue(hmq); } WinTerminate(hab); } } pib->pib_ultype = oldType;#endif}int resize_window(int x, int y){ int xfont, yfont; A_DECL(VIOMODEINFO, vmi); resize_count++; if (is_xterm()) return -1; vmi->cb = sizeof(*vmi); if (VioGetMode(vmi, 0)) return -1; vmi->col = x; vmi->row = y; /*debug("%d %d %d", vmi->buf_length, vmi->full_length, vmi->partial_length);*/ for (xfont = 9; xfont >= 8; xfont--) for (yfont = 16; yfont >= 8; yfont--) { vmi->hres = x * xfont; vmi->vres = y * yfont; if (vmi->vres <= 400) vmi->vres = 400; else if (vmi->vres <= 480) vmi->vres = 480; vmi->buf_length = vmi->full_length = vmi->partial_length = x * ((vmi->vres + yfont - 1) / yfont) * 2; vmi->full_length = (vmi->full_length + 4095) & ~4095; vmi->partial_length = (vmi->partial_length + 4095) & ~4095; if (!VioSetMode(vmi, 0)) return 0; } return -1;}#endif/* Threads */struct tdata { void (*fn)(void *, int); int h; unsigned char data[1];};#if defined(HAVE_BEGINTHREAD) || defined(BEOS) || defined(HAVE_PTHREADS) || defined(HAVE_ATHEOS_THREADS_H)static void bgt(struct tdata *t){ ignore_signals(); t->fn(t->data, t->h); write(t->h, "x", 1); close(t->h); free(t);}#ifdef HAVE_PTHREADSstatic void *bgpt(struct tdata *t){ bgt(t); return NULL;}#endif#ifdef HAVE_ATHEOS_THREADS_H#include <atheos/threads.h>static uint32 abgt(void *t){ bgt(t); return 0;}#endif#endif#if defined(UNIX) || defined(OS2) || defined(RISCOS) || defined(ATHEOS) || defined(SPAD) || defined(WIN32)void terminate_osdep(void) {}#endif#ifndef BEOSvoid block_stdin(void) {}void unblock_stdin(void) {}#endif#if defined(BEOS)#include <be/kernel/OS.h>int thr_sem_init = 0;sem_id thr_sem;struct list_head active_threads = { &active_threads, &active_threads };struct active_thread { struct active_thread *next; struct active_thread *prev; thread_id tid; void (*fn)(void *); void *data;};int32 started_thr(void *data){ struct active_thread *thrd = data; thrd->fn(thrd->data); if (acquire_sem(thr_sem) < B_NO_ERROR) return 0; del_from_list(thrd); free(thrd); release_sem(thr_sem); return 0;}int start_thr(void (*fn)(void *), void *data, unsigned char *name){ struct active_thread *thrd; int tid; if (!thr_sem_init) { if ((thr_sem = create_sem(0, "thread_sem")) < B_NO_ERROR) return -1; thr_sem_init = 1; } else if (acquire_sem(thr_sem) < B_NO_ERROR) return -1; if (!(thrd = malloc(sizeof(struct active_thread)))) goto rel; thrd->fn = fn; thrd->data = data; if ((tid = thrd->tid = spawn_thread(started_thr, name, B_NORMAL_PRIORITY, thrd)) < B_NO_ERROR) { free(thrd); rel: release_sem(thr_sem); return -1; } resume_thread(thrd->tid); add_to_list(active_threads, thrd); release_sem(thr_sem); return tid;}void terminate_osdep(void){ struct list_head *p; struct active_thread *thrd; if (acquire_sem(thr_sem) < B_NO_ERROR) return; foreach(thrd, active_threads) kill_thread(thrd->tid); while ((p = active_threads.next) != &active_threads) { del_from_list(p); free(p); } release_sem(thr_sem);}int start_thread(void (*fn)(void *, int), void *ptr, int l){ int p[2]; struct tdata *t; if (c_pipe(p) < 0) return -1; if (!(t = malloc(sizeof(struct tdata) + l))) return -1; t->fn = fn; t->h = p[1]; memcpy(t->data, ptr, l); if (start_thr((void (*)(void *))bgt, t, "links_thread") < 0) { close(p[0]); close(p[1]); mem_free(t); return -1; } return p[0];}#elif defined(HAVE_BEGINTHREAD)int start_thread(void (*fn)(void *, int), void *ptr, int l){ int p[2]; struct tdata *t; if (c_pipe(p) < 0) return -1; fcntl(p[0], F_SETFL, O_NONBLOCK); fcntl(p[1], F_SETFL, O_NONBLOCK); if (!(t = malloc(sizeof(struct tdata) + l))) return -1; t->fn = fn; t->h = p[1]; memcpy(t->data, ptr, l); if (_beginthread((void (*)(void *))bgt, NULL, 65536, t) == -1) { close(p[0]); close(p[1]); mem_free(t); return -1; } return p[0];}#ifdef HAVE_READ_KBDint tp = -1;int ti = -1;static void input_thread(void *p){ char c[2]; int h = (int)p; ignore_signals(); while (1) { /*c[0] = _read_kbd(0, 1, 1); if (c[0]) if (write(h, c, 1) <= 0) break; else { int w; printf("1");fflush(stdout); c[1] = _read_kbd(0, 1, 1); printf("2");fflush(stdout); w = write(h, c, 2); printf("3");fflush(stdout); if (w <= 0) break; if (w == 1) if (write(h, c+1, 1) <= 0) break; printf("4");fflush(stdout); }*/ /* for the records: _read_kbd(0, 1, 1) will read a char, don't echo it, wait for one available and accept CTRL-C. Knowing that, I suggest we replace this call completly! */ *c = _read_kbd(0, 1, 1); write(h, c, 1); } close(h);}#endif /* #ifdef HAVE_READ_KBD */#if defined(HAVE_MOUOPEN) && !defined(USE_GPM)#define USING_OS2_MOUSE#ifdef HAVE_SYS_FMUTEX_H_fmutex mouse_mutex;int mouse_mutex_init = 0;#endifint mouse_h = -1;struct os2_mouse_spec { int p[2]; void (*fn)(void *, unsigned char *, int); void *data; unsigned char buffer[sizeof(struct event)]; int bufptr; int terminate;};static void mouse_thread(void *p){ int status; struct os2_mouse_spec *oms = p; A_DECL(HMOU, mh); A_DECL(MOUEVENTINFO, ms); A_DECL(USHORT, rd); A_DECL(USHORT, mask); struct event ev; ignore_signals(); ev.ev = EV_MOUSE; if (MouOpen(NULL, mh)) goto ret; mouse_h = *mh; *mask = MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN1_DOWN | MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_BN2_DOWN | MOUSE_MOTION_WITH_BN3_DOWN | MOUSE_BN3_DOWN | MOUSE_MOTION; MouSetEventMask(mask, *mh); *rd = MOU_WAIT; status = -1; while (1) { /*int w, ww;*/ if (MouReadEventQue(ms, rd, *mh)) break;#ifdef HAVE_SYS_FMUTEX_H _fmutex_request(&mouse_mutex, _FMR_IGNINT);#endif if (!oms->terminate) MouDrawPtr(*mh);#ifdef HAVE_SYS_FMUTEX_H _fmutex_release(&mouse_mutex);#endif ev.x = ms->col; ev.y = ms->row; /*debug("status: %d %d %d", ms->col, ms->row, ms->fs);*/ if (ms->fs & (MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN)) ev.b = status = B_DOWN | (ms->fs & MOUSE_BN1_DOWN ? B_LEFT : ms->fs & MOUSE_BN2_DOWN ? B_MIDDLE : B_RIGHT); else if (ms->fs & (MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_MOTION_WITH_BN3_DOWN)) { int b = ms->fs & MOUSE_MOTION_WITH_BN1_DOWN ? B_LEFT : ms->fs & MOUSE_MOTION_WITH_BN2_DOWN ? B_MIDDLE : B_RIGHT; if (status == -1) b |= B_DOWN; else b |= B_DRAG; ev.b = status = b; } else { if (status == -1) continue; ev.b = (status & BM_BUTT) | B_UP; status = -1; } if (hard_write(oms->p[1], (unsigned char *)&ev, sizeof(struct event)) != sizeof(struct event)) break; }#ifdef HAVE_SYS_FMUTEX_H _fmutex_request(&mouse_mutex, _FMR_IGNINT);#endif mouse_h = -1; MouClose(*mh);#ifdef HAVE_SYS_FMUTEX_H _fmutex_release(&mouse_mutex);#endif ret: close(oms->p[1]); /*free(oms);*/}static void mouse_handle(struct os2_mouse_spec *oms){ int r; if ((r = read(oms->p[0], oms->buffer + oms->bufptr, sizeof(struct event) - oms->bufptr)) <= 0) { unhandle_mouse(oms); return; } if ((oms->bufptr += r) == sizeof(struct event)) { oms->bufptr = 0; oms->fn(oms->data, oms->buffer, sizeof(struct event)); }}void *handle_mouse(int cons, void (*fn)(void *, unsigned char *, int), void *data){ struct os2_mouse_spec *oms; if (is_xterm()) return NULL;#ifdef HAVE_SYS_FMUTEX_H if (!mouse_mutex_init) { if (_fmutex_create(&mouse_mutex, 0)) return NULL; mouse_mutex_init = 1; }#endif /* This is never freed but it's allocated only once */ if (!(oms = malloc(sizeof(struct os2_mouse_spec)))) return NULL; oms->fn = fn; oms->data = data; oms->bufptr = 0; oms->terminate = 0; if (c_pipe(oms->p)) { free(oms); return NULL; } _beginthread(mouse_thread, NULL, 0x10000, (void *)oms); set_handlers(oms->p[0], (void (*)(void *))mouse_handle, NULL, NULL, oms); return oms;}void unhandle_mouse(void *om){ struct os2_mouse_spec *oms = om; want_draw(); oms->terminate = 1; set_handlers(oms->p[0], NULL, NULL, NULL, NULL); close(oms->p[0]); done_draw();}void want_draw(void){ A_DECL(NOPTRRECT, pa);#ifdef HAVE_SYS_FMUTEX_H if (mouse_mutex_init) _fmutex_request(&mouse_mutex, _FMR_IGNINT);#endif if (mouse_h != -1) { static int x = -1, y = -1; static tcount c = -1; if (x == -1 || y == -1 || (c != resize_count)) get_terminal_size(1, &x, &y), c = resize_count; pa->row = 0; pa->col = 0; pa->cRow = y - 1; pa->cCol = x - 1; MouRemovePtr(pa, mouse_h); }}void done_draw(void){#ifdef HAVE_SYS_FMUTEX_H if (mouse_mutex_init) _fmutex_release(&mouse_mutex);#endif}#endif /* if HAVE_MOUOPEN */#elif defined(HAVE_CLONE)/* This is maybe buggy... */#include <sched.h>struct thread_stack { struct thread_stack *next; struct thread_stack *prev; int pid; void *stack; void (*fn)(void *, int); int h; int l; unsigned char data[1];};void bglt(struct thread_stack *ts){ ts->fn(ts->data, ts->h); write(ts->h, "x", 1); close(ts->h);}struct list_head thread_stacks = { &thread_stacks, &thread_stacks };int start_thread(void (*fn)(void *, int), void *ptr, int l){ struct thread_stack *ts; int p[2]; int f; if (c_pipe(p) < 0) return -1; fcntl(p[0], F_SETFL, O_NONBLOCK); fcntl(p[1], F_SETFL, O_NONBLOCK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -