about summary refs log tree commit diff stats
path: root/src/ui/console.c
Commit message (Expand)AuthorAgeFilesLines
* Added aliases to autocompleteJames Booth2014-01-231-7/+0
* Added /alias command, writing aliases to [alias] group in profrcJames Booth2014-01-231-0/+16
* Added skeleton /alias commandJames Booth2014-01-231-0/+7
* Added statuses settings to prefs outputJames Booth2014-01-211-20/+28
* Added UI presence functionsJames Booth2014-01-191-0/+36
* Added port to /account show <account>James Booth2014-01-191-0/+3
* Show OTR coloured statusJames Booth2014-01-161-0/+12
* Added setting /otr log on|off|redactJames Booth2014-01-131-0/+16
* Added /otr theirfp with hardcoded fingerprintJames Booth2014-01-111-1/+1
* Tidied navigation helpJames Booth2014-01-021-4/+2
* Added full stop to /help service summaryJames Booth2014-01-021-1/+1
* Removed wins_refresh_console when not required for /sub command outputJames Booth2013-12-271-2/+0
* Bind console functions in main.cJames Booth2013-12-231-64/+66
* Dynamically load UI functions, fixed testsJames Booth2013-12-221-120/+183
* Added mocks and stubs for cons_showJames Booth2013-12-191-2/+3
* Added simple mock test, refactored rosterJames Booth2013-12-141-1/+1
* Merge branch 'master' into refactor2James Booth2013-11-111-0/+13
|\
| * Allow "account" setting in [connection] to autconnect the accountJames Booth2013-11-071-0/+10
| * Merge remote-tracking branch 'tsenart/passwords-on-accounts-file'James Booth2013-11-071-0/+3
| |\
| | * Use passwords from the accounts fileTomás Senart2013-10-141-0/+1
| |/
* | Removed generic functions from ProfWinJames Booth2013-10-061-77/+77
* | Use ProfWin->print_line for console typing notificationsJames Booth2013-10-061-4/+1
|/
* OO style for ProfWin typeJames Booth2013-10-061-77/+79
* Adding irssi style Alt-Left/Right window navigationJesse R. Adams2013-09-251-0/+2
* Added git branch and revision to development buildsJames Booth2013-09-171-0/+12
* Allow users to set default muc service and nickname per accountJames Booth2013-09-121-0/+6
* Show correct window number for incoming in consoleJames Booth2013-08-281-1/+2
* Changes to status bar for unlimited windows - WIPJames Booth2013-08-281-1/+1
* Moved static function in console.cJames Booth2013-08-261-76/+76
* Removed cons_create from console.cJames Booth2013-08-261-9/+0
* Fix console references after merging masterJames Booth2013-08-251-1/+3
* Merge branch 'master' into windowsJames Booth2013-08-251-6/+35
|\
| * removed strdup from g_string_appendDmitry Podgorny2013-08-251-5/+5
| * most FREE_SET_NULL replaced with freeDmitry Podgorny2013-08-031-1/+1
| * draft of bookmarks implementationDmitry Podgorny2013-07-141-0/+29
* | Console module get console from windowsJames Booth2013-08-201-4/+23
* | Initial code refactor for growable window listJames Booth2013-08-201-106/+49
|/
* Coloured contact and subscription in /roster and /group outputJames Booth2013-07-031-55/+62
* Show current setting with settings commandsJames Booth2013-06-251-37/+150
* Restructured helpJames Booth2013-06-251-76/+11
* Added group add and group remove to /roster commandJames Booth2013-06-021-0/+60
* Added roster list when using /roster with no argsJames Booth2013-06-011-0/+36
* Include subscription states of "both" and "to" in /who outputJames Booth2013-06-011-1/+2
* Added /leave commandJames Booth2013-05-301-42/+42
* Show nickname rather than jid in room invitesJames Booth2013-05-301-2/+16
* Finished handle usageJames Booth2013-05-201-5/+13
* Added sub to /notify preferences outputJames Booth2013-05-191-6/+11
* Show 0 rather than 10 in /winsJames Booth2013-05-161-4/+9
* Fixed incoming message text in console to use 0 rather than 10James Booth2013-05-161-1/+5
* Removed contact_list, moved roster logic to xmpp/roster moduleJames Booth2013-05-061-1/+1
>{ c->snext = stack; stack = c; } static void detachstack(Client *c) { Client **tc; for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); *tc = c->snext; } static void grabbuttons(Client *c, Bool focused) { XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if(focused) { XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } else XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } static Bool isprotodel(Client *c) { int i, n; Atom *protocols; Bool ret = False; if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { for(i = 0; !ret && i < n; i++) if(protocols[i] == wmatom[WMDelete]) ret = True; XFree(protocols); } return ret; } static void setclientstate(Client *c, long state) { long data[] = {state, None}; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, PropModeReplace, (unsigned char *)data, 2); } static int xerrordummy(Display *dsply, XErrorEvent *ee) { return 0; } /* extern */ void attach(Client *c) { if(clients) clients->prev = c; c->next = clients; clients = c; } void ban(Client *c) { if(c->isbanned) return; XUnmapWindow(dpy, c->win); setclientstate(c, IconicState); c->isbanned = True; c->unmapped++; } void configure(Client *c) { XConfigureEvent ce; ce.type = ConfigureNotify; ce.display = dpy; ce.event = c->win; ce.window = c->win; ce.x = c->x; ce.y = c->y; ce.width = c->w; ce.height = c->h; ce.border_width = c->border; ce.above = None; ce.override_redirect = False; XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); } void detach(Client *c) { if(c->prev) c->prev->next = c->next; if(c->next) c->next->prev = c->prev; if(c == clients) clients = c->next; c->next = c->prev = NULL; } void focus(Client *c) { if((!c && selscreen) || (c && !isvisible(c))) for(c = stack; c && !isvisible(c); c = c->snext); if(sel && sel != c) { grabbuttons(sel, False); XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); } if(c) { detachstack(c); attachstack(c); grabbuttons(c, True); } sel = c; drawstatus(); if(!selscreen) return; if(c) { XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); } else XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); } void killclient(const char *arg) { XEvent ev; if(!sel) return; if(isprotodel(sel)) { ev.type = ClientMessage; ev.xclient.window = sel->win; ev.xclient.message_type = wmatom[WMProtocols]; ev.xclient.format = 32; ev.xclient.data.l[0] = wmatom[WMDelete]; ev.xclient.data.l[1] = CurrentTime; XSendEvent(dpy, sel->win, False, NoEventMask, &ev); } else XKillClient(dpy, sel->win); } void manage(Window w, XWindowAttributes *wa) { Client *c, *t = NULL; Window trans; Status rettrans; XWindowChanges wc; c = emallocz(sizeof(Client)); c->tags = emallocz(ntags * sizeof(Bool)); c->win = w; c->x = wa->x; c->y = wa->y; c->w = wa->width; c->h = wa->height; c->oldborder = wa->border_width; if(c->w == sw && c->h == sh) { c->x = sx; c->y = sy; c->border = wa->border_width; } else { if(c->x + c->w + 2 * c->border > wax + waw) c->x = wax + waw - c->w - 2 * c->border; if(c->y + c->h + 2 * c->border > way + wah) c->y = way + wah - c->h - 2 * c->border; if(c->x < wax) c->x = wax; if(c->y < way) c->y = way; c->border = BORDERPX; } wc.border_width = c->border; XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, dc.norm[ColBorder]); configure(c); /* propagates border_width, if size doesn't change */ updatesizehints(c); XSelectInput(dpy, w, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); grabbuttons(c, False); updatetitle(c); if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) for(t = clients; t && t->win != trans; t = t->next); settags(c, t); if(!c->isfloating) c->isfloating = (rettrans == Success) || c->isfixed; attach(c); attachstack(c); XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, IconicState); c->isbanned = True; focus(c); lt->arrange(NULL); } void resize(Client *c, int x, int y, int w, int h, Bool sizehints) { float dx, dy, max, min, ratio; XWindowChanges wc; if(w <= 0 || h <= 0) return; if(sizehints) { if(c->minay > 0 && c->maxay > 0 && (h - c->baseh) > 0) { dx = (float)(w - c->basew); dy = (float)(h - c->baseh); min = (float)(c->minax) / (float)(c->minay); max = (float)(c->maxax) / (float)(c->maxay); ratio = dx / dy; if(max > 0 && min > 0 && ratio > 0) { if(ratio < min) { dy = (dx * min + dy) / (min * min + 1); dx = dy * min; w = (int)dx + c->basew; h = (int)dy + c->baseh; } else if(ratio > max) { dy = (dx * min + dy) / (max * max + 1); dx = dy * min; w = (int)dx + c->basew; h = (int)dy + c->baseh; } } } if(c->minw && w < c->minw) w = c->minw; if(c->minh && h < c->minh) h = c->minh; if(c->maxw && w > c->maxw) w = c->maxw; if(c->maxh && h > c->maxh) h = c->maxh; if(c->incw) w -= (w - c->basew) % c->incw; if(c->inch) h -= (h - c->baseh) % c->inch; } if(w <= 0 || h <= 0) return; /* offscreen appearance fixes */ if(x > sw) x = sw - w - 2 * c->border; if(y > sh) y = sh - h - 2 * c->border; if(x + w + 2 * c->border < sx) x = sx; if(y + h + 2 * c->border < sy) y = sy; if(c->x != x || c->y != y || c->w != w || c->h != h) { c->x = wc.x = x; c->y = wc.y = y; c->w = wc.width = w; c->h = wc.height = h; wc.border_width = c->border; XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); configure(c); XSync(dpy, False); } } void togglefloating(const char *arg) { if(!sel || lt->arrange == floating) return; sel->isfloating = !sel->isfloating; if(sel->isfloating) resize(sel, sel->x, sel->y, sel->w, sel->h, True); lt->arrange(NULL); } void unban(Client *c) { if(!c->isbanned) return; XMapWindow(dpy, c->win); setclientstate(c, NormalState); c->isbanned = False; } void unmanage(Client *c) { XWindowChanges wc; wc.border_width = c->oldborder; /* The server grab construct avoids race conditions. */ XGrabServer(dpy); XSetErrorHandler(xerrordummy); XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ detach(c); detachstack(c); if(sel == c) focus(NULL); XUngrabButton(dpy, AnyButton, AnyModifier, c->win); setclientstate(c, WithdrawnState); free(c->tags); free(c); XSync(dpy, False); XSetErrorHandler(xerror); XUngrabServer(dpy); lt->arrange(NULL); } void updatesizehints(Client *c) { long msize; XSizeHints size; if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) size.flags = PSize; c->flags = size.flags; if(c->flags & PBaseSize) { c->basew = size.base_width; c->baseh = size.base_height; } else if(c->flags & PMinSize) { c->basew = size.min_width; c->baseh = size.min_height; } else c->basew = c->baseh = 0; if(c->flags & PResizeInc) { c->incw = size.width_inc; c->inch = size.height_inc; } else c->incw = c->inch = 0; if(c->flags & PMaxSize) { c->maxw = size.max_width; c->maxh = size.max_height; } else c->maxw = c->maxh = 0; if(c->flags & PMinSize) { c->minw = size.min_width; c->minh = size.min_height; } else if(c->flags & PBaseSize) { c->minw = size.base_width; c->minh = size.base_height; } else c->minw = c->minh = 0; if(c->flags & PAspect) { c->minax = size.min_aspect.x; c->maxax = size.max_aspect.x; c->minay = size.min_aspect.y; c->maxay = size.max_aspect.y; } else c->minax = c->maxax = c->minay = c->maxay = 0; c->isfixed = (c->maxw && c->minw && c->maxh && c->minh && c->maxw == c->minw && c->maxh == c->minh); } void updatetitle(Client *c) { char **list = NULL; int n; XTextProperty name; name.nitems = 0; c->name[0] = 0; XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); if(!name.nitems) XGetWMName(dpy, c->win, &name); if(!name.nitems) return; if(name.encoding == XA_STRING) strncpy(c->name, (char *)name.value, sizeof c->name - 1); else { if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { strncpy(c->name, *list, sizeof c->name - 1); XFreeStringList(list); } } c->name[sizeof c->name - 1] = '\0'; XFree(name.value); }