about summary refs log tree commit diff stats
path: root/draw.c
Commit message (Expand)AuthorAgeFilesLines
...
* implemented right tag drawing in the status bar and titlebarsAnselm R. Garbe2006-08-231-10/+21
* tags appear in the left againAnselm R. Garbe2006-08-231-5/+5
* titlebars contain tags in the right nowAnselm R. Garbe2006-08-221-6/+5
* fixed string cuttingAnselm R.Garbe2006-08-141-6/+6
* fixed string cutting in draw.cAnselm R.Garbe2006-08-141-2/+10
* implemented viewextend and added M-S-C-n shortcuts for extending the current ...Anselm R.Garbe2006-08-111-2/+2
* implement multi-tag selection through button3 click on the specific tagAnselm R.Garbe2006-08-111-2/+2
* simplified drawtextAnselm R.Garbe2006-08-111-21/+14
* applied sumik's multihead patchAnselm R.Garbe2006-08-101-1/+1
* readded border color, this sucks leastAnselm R.Garbe2006-08-101-14/+22
* drawing border with fg colorAnselm R.Garbe2006-08-101-1/+14
* removed unnecessary border colorAnselm R.Garbe2006-08-101-21/+0
* changed signature of drawtextarg@10ksloc.org2006-08-071-12/+10
* status box should have a border in my eyesarg@10ksloc.org2006-08-071-1/+1
* removed TLast tag enum, now tags is simple defined as char *[] array, the res...arg@10ksloc.org2006-08-031-2/+2
* changed Client->tags and Rule->tags to be Bool (I'll also try to remove the T...arg@10ksloc.org2006-08-031-4/+4
* made fullscreen apps working fine in floating mode (there is no sane way to m...arg@10ksloc.org2006-08-021-1/+0
* committed a patch which fixes the hints of Jukkaarg@10ksloc.org2006-08-011-1/+1
* made status bar drawing more robust, implemented togglemax and togglemode, wo...arg@10ksloc.org2006-07-201-7/+6
* cleaned up codearg@10ksloc.org2006-07-201-2/+4
* added heretag command which allows to tag a client of a foreign tag with curr...Anselm R. Garbe2006-07-181-1/+1
* ordered variables in structs and source files alphabeticallyAnselm R. Garbe2006-07-171-2/+2
* fixed XSync handling and finished man pageAnselm R. Garbe2006-07-151-4/+3
* sanitized other stuffAnselm R. Garbe2006-07-151-52/+52
* proceeded with cleaning up, sorting functions, etcAnselm R. Garbe2006-07-151-72/+74
* rearranged several stuffAnselm R. Garbe2006-07-151-13/+24
* sanitized namesAnselm R. Garbe2006-07-141-5/+5
* rearrangedAnselm R. Garbe2006-07-141-1/+66
* removed a bunch of lines through swap removalAnselm R. Garbe2006-07-141-4/+4
* implemented bar for dwm (I miss status text), I plan that status text is read...Anselm R. Garbe2006-07-141-1/+1
* changed default colorsAnselm R. Garbe2006-07-131-51/+38
* added logo+descriptionAnselm R. Garbe2006-07-131-37/+36
* new stuff (some warning elimination)Anselm R. Garbe2006-07-131-14/+13
* removed unnecessary crapAnselm R. Garbe2006-07-131-2/+3
* new stuff, fixed several issuesAnselm R. Garbe2006-07-121-0/+1
* simplified several portions of code through replacing rect structs with x,y,h...Anselm R. Garbe2006-07-121-22/+23
* new stuffAnselm R. Garbe2006-07-111-3/+3
* added several other stuffAnselm R. Garbe2006-07-101-0/+6
* several new changes, made gridmenu workingAnselm R. Garbe2006-07-101-20/+21
* added new stuffAnselm R. Garbe2006-07-101-0/+163
"w"> PSym proc instantiateDestructor(c: PContext, typ: PType): PType proc doDestructorStuff(c: PContext, s: PSym, n: PNode) = var t = s.typ.sons[1].skipTypes({tyVar}) if t.kind == tyGenericInvokation: for i in 1 .. <t.sonsLen: if t.sons[i].kind != tyGenericParam: localError(n.info, errDestructorNotGenericEnough) return t = t.base elif t.kind == tyCompositeTypeClass: t = t.base if t.kind != tyGenericBody: localError(n.info, errDestructorNotGenericEnough) return t.destructor = s # automatically insert calls to base classes' destructors if n.sons[bodyPos].kind != nkEmpty: for i in countup(0, t.sonsLen - 1): # when inheriting directly from object # there will be a single nil son if t.sons[i] == nil: continue let destructableT = instantiateDestructor(c, t.sons[i]) if destructableT != nil: n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[ useSym(destructableT.destructor), n.sons[paramsPos][1][0]])) proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode proc destroySym(c: PContext, field: PSym, holder: PNode): PNode = let destructableT = instantiateDestructor(c, field.typ) if destructableT != nil: result = newNode(nkCall, field.info, @[ useSym(destructableT.destructor), newNode(nkDotExpr, field.info, @[holder, useSym(field)])]) proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode = var nonTrivialFields = 0 result = newNode(nkCaseStmt, n.info, @[]) # case x.kind result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]])) for i in countup(1, n.len - 1): # of A, B: var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2]) let stmt = destroyFieldOrFields(c, n[i].lastSon, holder) if stmt == nil: caseBranch.addSon(newNode(nkStmtList, n[i].info, @[])) else: caseBranch.addSon(stmt) nonTrivialFields += stmt.len result.addSon(caseBranch) # maybe no fields were destroyed? if nonTrivialFields == 0: result = nil proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode = template maybeAddLine(e: expr): stmt = let stmt = e if stmt != nil: if result == nil: result = newNode(nkStmtList) result.addSon(stmt) case field.kind of nkRecCase: maybeAddLine destroyCase(c, field, holder) of nkSym: maybeAddLine destroySym(c, field.sym, holder) of nkRecList: for son in field: maybeAddLine destroyFieldOrFields(c, son, holder) else: internalAssert false proc generateDestructor(c: PContext, t: PType): PNode = ## generate a destructor for a user-defined object or tuple type ## returns nil if the destructor turns out to be trivial # XXX: This may be true for some C-imported types such as # Tposix_spawnattr if t.n == nil or t.n.sons == nil: return internalAssert t.n.kind == nkRecList let destructedObj = newIdentNode(destructorParam, unknownLineInfo()) # call the destructods of all fields result = destroyFieldOrFields(c, t.n, destructedObj) # base classes' destructors will be automatically called by # semProcAux for both auto-generated and user-defined destructors proc instantiateDestructor(c: PContext, typ: PType): PType = # returns nil if a variable of type `typ` doesn't require a # destructor. Otherwise, returns the type, which holds the # destructor that must be used for the varialbe. # The destructor is either user-defined or automatically # generated by the compiler in a member-wise fashion. var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t if typeHoldingUserDefinition.destructor != nil: # XXX: This is not entirely correct for recursive types, but we need # it temporarily to hide the "destroy is already defined" problem if typeHoldingUserDefinition.destructor notin [analyzingDestructor, destructorIsTrivial]: return typeHoldingUserDefinition else: return nil t = t.skipTypes({tyGenericInst}) case t.kind of tySequence, tyArray, tyArrayConstr, tyOpenArray, tyVarargs: if instantiateDestructor(c, t.sons[0]) != nil: if rangeDestructorProc == nil: rangeDestructorProc = searchInScopes(c, getIdent"nimDestroyRange") t.destructor = rangeDestructorProc return t else: return nil of tyTuple, tyObject: t.destructor = analyzingDestructor let generated = generateDestructor(c, t) if generated != nil: internalAssert t.sym != nil var i = t.sym.info let fullDef = newNode(nkProcDef, i, @[ newIdentNode(destructorName, i), emptyNode, emptyNode, newNode(nkFormalParams, i, @[ emptyNode, newNode(nkIdentDefs, i, @[ newIdentNode(destructorParam, i), symNodeFromType(c, makeVarType(c, t), t.sym.info), emptyNode]), ]), newNode(nkPragma, i, @[destructorPragma]), emptyNode, generated ]) let semantizedDef = semProc(c, fullDef) t.destructor = semantizedDef[namePos].sym return t else: t.destructor = destructorIsTrivial return nil else: return nil proc insertDestructors(c: PContext, varSection: PNode): tuple[outer, inner: PNode] = # Accepts a var or let section. # # When a var section has variables with destructors # the var section is split up and finally blocks are inserted # immediately after all "destructable" vars # # In case there were no destrucable variables, the proc returns # (nil, nil) and the enclosing stmt-list requires no modifications. # # Otherwise, after the try blocks are created, the rest of the enclosing # stmt-list should be inserted in the most `inner` such block (corresponding # to the last variable). # # `outer` is a statement list that should replace the original var section. # It will include the new truncated var section followed by the outermost # try block. let totalVars = varSection.sonsLen for j in countup(0, totalVars - 1): let varId = varSection[j][0] varTyp = varId.sym.typ info = varId.info if varTyp == nil or sfGlobal in varId.sym.flags: continue let destructableT = instantiateDestructor(c, varTyp) if destructableT != nil: var tryStmt = newNodeI(nkTryStmt, info) if j < totalVars - 1: var remainingVars = newNodeI(varSection.kind, info) remainingVars.sons = varSection.sons[(j+1)..(-1)] let (outer, inner) = insertDestructors(c, remainingVars) if outer != nil: tryStmt.addSon(outer) result.inner = inner else: result.inner = newNodeI(nkStmtList, info) result.inner.addSon(remainingVars) tryStmt.addSon(result.inner) else: result.inner = newNodeI(nkStmtList, info) tryStmt.addSon(result.inner) tryStmt.addSon( newNode(nkFinally, info, @[ semStmt(c, newNode(nkCall, info, @[ useSym(destructableT.destructor), useSym(varId.sym)]))])) result.outer = newNodeI(nkStmtList, info) varSection.sons.setLen(j+1) result.outer.addSon(varSection) result.outer.addSon(tryStmt) return